Remove X_DC_INFO from DC and make it behave like any other PDEVICE.
[wine] / windows / event.c
1 /*
2  * X events handling functions
3  * 
4  * Copyright 1993 Alexandre Julliard
5  * 
6  */
7
8 #include <assert.h>
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <errno.h>
16 #include <X11/keysym.h>
17 #include "ts_xlib.h"
18 #include "ts_xresource.h"
19 #include "ts_xutil.h"
20 #include <X11/Xatom.h>
21
22 #include "windows.h"
23 #include "winnt.h"
24 #include "gdi.h"
25 #include "heap.h"
26 #include "queue.h"
27 #include "win.h"
28 #include "class.h"
29 #include "clipboard.h"
30 #include "dce.h"
31 #include "message.h"
32 #include "module.h"
33 #include "options.h"
34 #include "queue.h"
35 #include "winpos.h"
36 #include "drive.h"
37 #include "shell.h"
38 #include "keyboard.h"
39 #include "mouse.h"
40 #include "debug.h"
41 #include "dde_proc.h"
42 #include "winsock.h"
43 #include "mouse.h"
44 #include "x11drv.h"
45
46 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
47
48 #define DndNotDnd       -1    /* OffiX drag&drop */
49 #define DndUnknown      0
50 #define DndRawData      1
51 #define DndFile         2
52 #define DndFiles        3
53 #define DndText         4
54 #define DndDir          5
55 #define DndLink         6
56 #define DndExe          7
57
58 #define DndEND          8
59
60 #define DndURL          128   /* KDE drag&drop */
61
62
63   /* X context to associate a hwnd to an X window */
64 static XContext winContext = 0;
65
66 static Atom wmProtocols = None;
67 static Atom wmDeleteWindow = None;
68 static Atom dndProtocol = None;
69 static Atom dndSelection = None;
70
71 /* EVENT_WaitNetEvent() master fd sets */
72
73 static fd_set __event_io_set[3];
74 static int    __event_max_fd = 0;
75 static int    __event_x_connection = 0;
76
77 static const char * const event_names[] =
78 {
79     "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
80     "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
81     "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
82     "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
83     "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
84     "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
85     "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
86     "ClientMessage", "MappingNotify"
87 };
88
89   /* Event handlers */
90 static void EVENT_Key( WND *pWnd, XKeyEvent *event );
91 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event );
92 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event );
93 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event );
94 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event );
95 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event );
96 static int  EVENT_Expose( WND *pWnd, XExposeEvent *event );
97 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
98 static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event );
99 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
100 static void EVENT_SelectionNotify( XSelectionEvent *event);
101 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
102 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
103 static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
104
105 /* Usable only with OLVWM - compile option perhaps?
106 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
107 */
108
109 static void EVENT_GetGeometry( Window win, int *px, int *py,
110                                unsigned int *pwidth, unsigned int *pheight );
111
112 /***********************************************************************
113  *           EVENT_Init
114  *
115  * Initialize network IO.
116  */
117 BOOL32 EVENT_Init(void)
118 {
119     int  i;
120     for( i = 0; i < 3; i++ )
121         FD_ZERO( __event_io_set + i );
122
123     __event_max_fd = __event_x_connection = ConnectionNumber(display);
124     FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] );
125     __event_max_fd++;
126     return TRUE;
127 }
128
129 /***********************************************************************
130  *          EVENT_AddIO 
131  */
132 void EVENT_AddIO( int fd, unsigned io_type )
133 {
134     FD_SET( fd, &__event_io_set[io_type] );
135     if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
136 }
137
138 void EVENT_DeleteIO( int fd, unsigned io_type )
139 {
140     FD_CLR( fd, &__event_io_set[io_type] );
141 }
142
143 /***********************************************************************
144  *           EVENT_ProcessEvent
145  *
146  * Process an X event.
147  */
148 void EVENT_ProcessEvent( XEvent *event )
149 {
150     WND *pWnd;
151     
152     if ( TSXFindContext( display, event->xany.window, winContext,
153                          (char **)&pWnd ) != 0) {
154       if ( event->type == ClientMessage) {
155         /* query window (drag&drop event contains only drag window) */
156         Window          root, child;
157         int             root_x, root_y, child_x, child_y;
158         unsigned        u;
159         TSXQueryPointer( display, rootWindow, &root, &child,
160                          &root_x, &root_y, &child_x, &child_y, &u);
161         if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0)
162           return;
163       } else {
164         pWnd = NULL;  /* Not for a registered window */
165       }
166     }
167
168     TRACE(event, "Got event %s for hwnd %04x\n",
169           event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
170
171     switch(event->type)
172     {
173     case KeyPress:
174     case KeyRelease:
175         EVENT_Key( pWnd, (XKeyEvent*)event );
176         break;
177         
178     case ButtonPress:
179         EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
180         break;
181
182     case ButtonRelease:
183         EVENT_ButtonRelease( pWnd, (XButtonEvent*)event );
184         break;
185
186     case MotionNotify:
187         /* Wine between two fast machines across the overloaded campus
188            ethernet gets very boged down in MotionEvents. The following
189            simply finds the last motion event in the queue and drops
190            the rest. On a good link events are servered before they build
191            up so this doesn't take place. On a slow link this may cause
192            problems if the event order is important. I'm not yet seen
193            of any problems. Jon 7/6/96.
194          */
195         while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
196                                         MotionNotify, event));    
197         EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
198         break;
199
200     case FocusIn:
201         if (!pWnd) return;
202         EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
203         break;
204
205     case FocusOut:
206         if (!pWnd) return;
207         EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
208         break;
209
210     case Expose:
211         if (!pWnd) return;
212         if (EVENT_Expose( pWnd, (XExposeEvent *)event )) {
213             /* need to process ConfigureNotify first */
214             XEvent new_event;
215
216             /* attempt to find and process the ConfigureNotify event now */
217             if (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
218                                           ConfigureNotify, &new_event)) {
219                 EVENT_ProcessEvent( &new_event );
220                 if (!EVENT_Expose( pWnd, (XExposeEvent *)event ))
221                     break;
222             }
223
224             /* no luck at this time, defer Expose event for later */
225             /* use "type" for an event counter, it is never rechecked */
226             if (!pWnd->expose_event) {
227                 pWnd->expose_event = malloc( sizeof(XExposeEvent) );
228                 pWnd->expose_event[0] = *(XExposeEvent *)event;
229                 pWnd->expose_event[0].type = 1;
230             } else {
231                 int i;
232
233                 i = ++pWnd->expose_event[0].type;
234                 pWnd->expose_event = realloc( pWnd->expose_event,
235                                               i * sizeof(XExposeEvent) );
236                 pWnd->expose_event[i-1] = *(XExposeEvent *)event;
237                 FIXME(x11, "Try and combine Expose events? %d queued.\n", i);
238             }
239         }
240         break;
241
242     case GraphicsExpose:
243         if (!pWnd) return;
244         EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
245         break;
246
247     case ConfigureNotify:
248         if (!pWnd) return;
249         EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event );
250         if (pWnd->expose_event) {
251             /* process deferred Expose event(s) */
252             int i;
253
254             for (i=0; i<pWnd->expose_event[0].type; i++) {
255                 if(EVENT_Expose( pWnd, &pWnd->expose_event[i] ))
256                     ERR(x11, "Unprocessed expose event discarded\n");
257             }
258             free( pWnd->expose_event );
259             pWnd->expose_event = NULL;
260         }
261         break;
262
263     case SelectionRequest:
264         if (!pWnd) return;
265         EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
266         break;
267
268     case SelectionNotify:
269         if (!pWnd) return;
270         EVENT_SelectionNotify( (XSelectionEvent *)event );
271         break;
272
273     case SelectionClear:
274         if (!pWnd) return;
275         EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
276         break;
277
278     case ClientMessage:
279         if (!pWnd) return;
280         EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
281         break;
282
283 /*  case EnterNotify:
284  *       EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
285  *       break;
286  */
287     case NoExpose:
288         break;
289
290     /* We get all these because of StructureNotifyMask. */
291     case UnmapNotify:
292     case CirculateNotify:
293     case CreateNotify:
294     case DestroyNotify:
295     case GravityNotify:
296     case ReparentNotify:
297         break;
298
299     case MapNotify:
300         if (!pWnd) return;
301         EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
302         break;
303
304     default:    
305         WARN(event, "Unprocessed event %s for hwnd %04x\n",
306                 event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
307         break;
308     }
309 }
310
311
312 /***********************************************************************
313  *           EVENT_RegisterWindow
314  *
315  * Associate an X window to a HWND.
316  */
317 void EVENT_RegisterWindow( WND *pWnd )
318 {
319     if (wmProtocols == None)
320         wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
321     if (wmDeleteWindow == None)
322         wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
323     if( dndProtocol == None )
324         dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
325     if( dndSelection == None )
326         dndSelection = TSXInternAtom( display, "DndSelection" , False );
327
328     TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
329
330     if (!winContext) winContext = TSXUniqueContext();
331     TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd );
332 }
333
334 /***********************************************************************
335  *           EVENT_DestroyWindow
336  */
337 void EVENT_DestroyWindow( WND *pWnd )
338 {
339    XEvent xe;
340
341    if (pWnd->expose_event) {
342        free( pWnd->expose_event );
343        pWnd->expose_event = NULL;
344    }
345    TSXDeleteContext( display, pWnd->window, winContext );
346    TSXDestroyWindow( display, pWnd->window );
347    while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
348 }
349
350
351 /***********************************************************************
352  *           IsUserIdle         (USER.333)
353  *
354  * Check if we have pending X events.
355  */
356 BOOL16 WINAPI IsUserIdle(void)
357 {
358     struct timeval timeout = {0, 0};
359     fd_set check_set;
360
361     FD_ZERO(&check_set);
362     FD_SET(__event_x_connection, &check_set);
363     if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 )
364         return TRUE;
365     return FALSE;
366 }
367
368
369 /***********************************************************************
370  *           EVENT_WaitNetEvent
371  *
372  * Wait for a network event, optionally sleeping until one arrives.
373  * Return TRUE if an event is pending, FALSE on timeout or error
374  * (for instance lost connection with the server).
375  */
376 BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
377 {
378     XEvent event;
379     LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
380     int pending = TSXPending(display);
381
382     /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
383      * in this case, we fall through directly to the XNextEvent loop.
384      */
385
386     if ((maxWait != -1) && !pending)
387     {
388         int num_pending;
389         struct timeval timeout;
390         fd_set io_set[3];
391
392         memcpy( io_set, __event_io_set, sizeof(io_set) );
393
394         timeout.tv_usec = (maxWait % 1000) * 1000;
395         timeout.tv_sec = maxWait / 1000;
396
397 #ifdef CONFIG_IPC
398         sigsetjmp(env_wait_x, 1);
399         stop_wait_op= CONT;
400             
401         if (DDE_GetRemoteMessage()) {
402             while(DDE_GetRemoteMessage())
403                 ;
404             return TRUE;
405         }
406         stop_wait_op = STOP_WAIT_X;
407         /* The code up to the next "stop_wait_op = CONT" must be reentrant */
408         num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], 
409                                               &io_set[EVENT_IO_WRITE], 
410                                               &io_set[EVENT_IO_EXCEPT], &timeout );
411         if ( num_pending == 0 )
412         {
413             stop_wait_op = CONT;
414             TIMER_ExpireTimers();
415             return FALSE;
416         }
417         else stop_wait_op = CONT;
418 #else  /* CONFIG_IPC */
419         num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
420                                               &io_set[EVENT_IO_WRITE],
421                                               &io_set[EVENT_IO_EXCEPT], &timeout );
422         if ( num_pending == 0)
423         {
424             /* Timeout or error */
425             TIMER_ExpireTimers();
426             return FALSE;
427         }
428 #endif  /* CONFIG_IPC */
429
430         /*  Winsock asynchronous services */
431
432         if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) 
433         {
434             num_pending--;
435             if( num_pending )
436                 WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
437         }
438         else /* no X events */
439             return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
440     }
441     else if(!pending)
442     {                           /* Wait for X11 input. */
443         fd_set set;
444
445         FD_ZERO(&set);
446         FD_SET(__event_x_connection, &set);
447         select(__event_x_connection + 1, &set, 0, 0, 0 );
448     }
449
450     /* Process current X event (and possibly others that occurred in the meantime) */
451
452     EnterCriticalSection(&X11DRV_CritSection);
453     while (XPending( display ))
454     {
455
456 #ifdef CONFIG_IPC
457         if (DDE_GetRemoteMessage())
458         {
459             LeaveCriticalSection(&X11DRV_CritSection);
460             while(DDE_GetRemoteMessage()) ;
461             return TRUE;
462         }
463 #endif  /* CONFIG_IPC */
464
465         XNextEvent( display, &event );
466
467         LeaveCriticalSection(&X11DRV_CritSection);
468         if( peek )
469         {
470           WND*          pWnd;
471           MESSAGEQUEUE* pQ;
472
473
474           /* Check only for those events which can be processed
475            * internally. */
476
477           if( event.type == MotionNotify ||
478               event.type == ButtonPress || event.type == ButtonRelease ||
479               event.type == KeyPress || event.type == KeyRelease ||
480               event.type == SelectionRequest || event.type == SelectionClear ||
481               event.type == ClientMessage )
482           {
483                EVENT_ProcessEvent( &event );
484                continue;
485           }
486
487           if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext,
488                             (char **)&pWnd ) || (event.type == NoExpose))
489               pWnd = NULL;
490
491           if( pWnd )
492           {
493             if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
494             {
495               pQ->flags |= QUEUE_FLAG_XEVENT;
496               PostEvent(pQ->hTask);
497               TSXPutBackEvent(display, &event);
498               break;
499             }
500           }
501         }
502         else EVENT_ProcessEvent( &event );
503         EnterCriticalSection(&X11DRV_CritSection);
504     }
505     LeaveCriticalSection(&X11DRV_CritSection);
506     return TRUE;
507 }
508
509
510 /***********************************************************************
511  *           EVENT_Synchronize
512  *
513  * Synchronize with the X server. Should not be used too often.
514  */
515 void EVENT_Synchronize()
516 {
517     XEvent event;
518
519     /* Use of the X critical section is needed or we have a small
520      * race between XPending() and XNextEvent().
521      */
522     EnterCriticalSection( &X11DRV_CritSection );
523     XSync( display, False );
524     while (XPending( display ))
525     {
526         XNextEvent( display, &event );
527         /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
528         LeaveCriticalSection( &X11DRV_CritSection );
529         EVENT_ProcessEvent( &event );
530         EnterCriticalSection( &X11DRV_CritSection );
531     }    
532     LeaveCriticalSection( &X11DRV_CritSection );
533 }
534
535 /***********************************************************************
536  *           EVENT_QueryZOrder
537  *
538  * Try to synchronize internal z-order with the window manager's.
539  * Probably a futile endeavor.
540  */
541 static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB )
542 {
543     /* return TRUE if we have at least two managed windows */
544
545     for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
546         if( (*pWndA)->flags & WIN_MANAGED &&
547             (*pWndA)->dwStyle & WS_VISIBLE ) break;
548     if( *pWndA )
549         for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
550             if( (*pWndB)->flags & WIN_MANAGED &&
551                 (*pWndB)->dwStyle & WS_VISIBLE ) break;
552      return ((*pWndB) != NULL);
553 }
554
555 static Window __get_common_ancestor( Window A, Window B,
556                                      Window** children, unsigned* total )
557 {
558     /* find the real root window */
559
560     Window      root, *childrenB;
561     unsigned    totalB;
562
563     do
564     {
565         if( *children ) TSXFree( *children );
566         TSXQueryTree( display, A, &root, &A, children, total );
567         TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
568         if( childrenB ) TSXFree( childrenB );
569     } while( A != B && A && B );
570     return ( A && B ) ? A : 0 ;
571 }
572
573 static Window __get_top_decoration( Window w, Window ancestor )
574 {
575     Window*     children, root, prev = w, parent = w;
576     unsigned    total;
577
578     do
579     {
580         w = parent;
581         TSXQueryTree( display, w, &root, &parent, &children, &total );
582         if( children ) TSXFree( children );
583     } while( parent && parent != ancestor );
584     TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
585     return ( parent ) ? w : 0 ;
586 }
587
588 static unsigned __td_lookup( Window w, Window* list, unsigned max )
589 {
590     unsigned    i;
591     for( i = 0; i < max; i++ ) if( list[i] == w ) break;
592     return i;
593 }
594
595 static BOOL32 EVENT_QueryZOrder( WND* pWndCheck )
596 {
597     BOOL32      bRet = FALSE;
598     HWND32      hwndInsertAfter = HWND_TOP;
599     WND*        pWnd, *pWndZ = WIN_GetDesktop()->child;
600     Window      w, parent, *children = NULL;
601     unsigned    total, check, pos, best;
602
603     if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE;
604
605     parent = __get_common_ancestor( pWndZ->window, pWnd->window,
606                                       &children, &total );
607     if( parent && children )
608     {
609         w = __get_top_decoration( pWndCheck->window, parent );
610         if( w != children[total - 1] )
611         {
612             check = __td_lookup( w, children, total );
613             best = total;
614             for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
615             {
616                 if( pWnd != pWndCheck )
617                 {
618                     if( !(pWnd->flags & WIN_MANAGED) ||
619                         !(w = __get_top_decoration( pWnd->window, parent )) )
620                         continue;
621                     pos = __td_lookup( w, children, total );
622                     if( pos < best && pos > check )
623                     {
624                         best = pos;
625                         hwndInsertAfter = pWnd->hwndSelf;
626                     }
627                     if( check - best == 1 ) break;
628                 }
629             }
630             WIN_UnlinkWindow( pWndCheck->hwndSelf );
631             WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
632         }
633     }
634     if( children ) TSXFree( children );
635     return bRet;
636 }
637
638
639 /***********************************************************************
640  *           EVENT_XStateToKeyState
641  *
642  * Translate a X event state (Button1Mask, ShiftMask, etc...) to
643  * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
644  */
645 static WORD EVENT_XStateToKeyState( int state )
646 {
647     int kstate = 0;
648     
649     if (state & Button1Mask) kstate |= MK_LBUTTON;
650     if (state & Button2Mask) kstate |= MK_MBUTTON;
651     if (state & Button3Mask) kstate |= MK_RBUTTON;
652     if (state & ShiftMask)   kstate |= MK_SHIFT;
653     if (state & ControlMask) kstate |= MK_CONTROL;
654     return kstate;
655 }
656
657 /***********************************************************************
658  *           EVENT_QueryPointer
659  */
660 BOOL32 EVENT_QueryPointer( DWORD *posX, DWORD *posY, DWORD *state )
661 {
662     Window root, child;
663     int rootX, rootY, winX, winY;
664     unsigned int xstate;
665
666     if (!TSXQueryPointer( display, rootWindow, &root, &child,
667                           &rootX, &rootY, &winX, &winY, &xstate )) 
668         return FALSE;
669
670     *posX  = (DWORD)winX;
671     *posY  = (DWORD)winY;
672     *state = EVENT_XStateToKeyState( xstate );
673
674     return TRUE;
675 }
676
677 /***********************************************************************
678  *           EVENT_Expose
679  */
680 static int EVENT_Expose( WND *pWnd, XExposeEvent *event )
681 {
682     RECT32 rect;
683     int x, y;
684     unsigned int width, height;
685
686     /* When scrolling, many (fvwm2-based) window managers send the Expose
687      * event before sending the ConfigureNotify event, and we don't like
688      * that, so before processing the Expose event, we check whether the
689      * geometry has changed, and if so, we defer the Expose event until
690      * we get the ConfigureNotify event.  -Ove KÃ¥ven */
691     EVENT_GetGeometry( event->window, &x, &y, &width, &height );
692
693     if ( x != pWnd->rectWindow.left || y != pWnd->rectWindow.top ||
694          (width != pWnd->rectWindow.right - pWnd->rectWindow.left) ||
695          (height != pWnd->rectWindow.bottom - pWnd->rectWindow.top))
696         return 1; /* tell EVENT_ProcessEvent() to defer it */
697
698     /* Make position relative to client area instead of window */
699     rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
700     rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
701     rect.right  = rect.left + event->width;
702     rect.bottom = rect.top + event->height;
703
704     PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
705                         RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
706                         (event->count ? 0 : RDW_ERASENOW), 0 );
707     return 0;
708 }
709
710
711 /***********************************************************************
712  *           EVENT_GraphicsExpose
713  *
714  * This is needed when scrolling area is partially obscured
715  * by non-Wine X window.
716  */
717 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
718 {
719     RECT32 rect;
720
721     /* Make position relative to client area instead of window */
722     rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
723     rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
724     rect.right  = rect.left + event->width;
725     rect.bottom = rect.top + event->height;
726
727     PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
728                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
729                         (event->count ? 0 : RDW_ERASENOW), 0 );
730 }
731
732
733 /***********************************************************************
734  *           EVENT_Key
735  *
736  * Handle a X key event
737  */
738 static void EVENT_Key( WND *pWnd, XKeyEvent *event )
739 {
740     KEYBOARD_HandleEvent( pWnd, event );
741 }
742
743
744 /***********************************************************************
745  *           EVENT_MotionNotify
746  */
747 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
748 {
749     int xOffset = pWnd? pWnd->rectWindow.left : 0;
750     int yOffset = pWnd? pWnd->rectWindow.top  : 0;
751
752     MOUSE_SendEvent( MOUSEEVENTF_MOVE, 
753                      xOffset + event->x, yOffset + event->y,
754                      EVENT_XStateToKeyState( event->state ), 
755                      event->time - MSG_WineStartTicks,
756                      pWnd? pWnd->hwndSelf : 0 );
757 }
758
759
760 /***********************************************************************
761  *           EVENT_DummyMotionNotify
762  *
763  * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
764  */
765 void EVENT_DummyMotionNotify(void)
766 {
767     DWORD winX, winY, state;
768
769     if ( EVENT_QueryPointer( &winX, &winY, &state ) )
770     {
771         MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state,
772                          GetTickCount(), 0 );
773     }
774 }
775
776
777 /***********************************************************************
778  *           EVENT_ButtonPress
779  */
780 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
781 {
782     static WORD statusCodes[NB_BUTTONS] = 
783         { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
784     int buttonNum = event->button - 1;
785
786     int xOffset = pWnd? pWnd->rectWindow.left : 0;
787     int yOffset = pWnd? pWnd->rectWindow.top  : 0;
788
789     if (buttonNum >= NB_BUTTONS) return;
790
791     MOUSE_SendEvent( statusCodes[buttonNum], 
792                      xOffset + event->x, yOffset + event->y,
793                      EVENT_XStateToKeyState( event->state ), 
794                      event->time - MSG_WineStartTicks,
795                      pWnd? pWnd->hwndSelf : 0 );
796 }
797
798
799 /***********************************************************************
800  *           EVENT_ButtonRelease
801  */
802 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
803 {
804     static WORD statusCodes[NB_BUTTONS] = 
805         { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
806     int buttonNum = event->button - 1;
807
808     int xOffset = pWnd? pWnd->rectWindow.left : 0;
809     int yOffset = pWnd? pWnd->rectWindow.top  : 0;
810
811     if (buttonNum >= NB_BUTTONS) return;    
812
813     MOUSE_SendEvent( statusCodes[buttonNum], 
814                      xOffset + event->x, yOffset + event->y,
815                      EVENT_XStateToKeyState( event->state ), 
816                      event->time - MSG_WineStartTicks,
817                      pWnd? pWnd->hwndSelf : 0 );
818 }
819
820
821 /**********************************************************************
822  *              EVENT_FocusIn
823  */
824 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
825 {
826     if (Options.managed) EVENT_QueryZOrder( pWnd );
827
828     if (event->detail != NotifyPointer)
829     { 
830         HWND32  hwnd = pWnd->hwndSelf;
831
832         if (hwnd != GetActiveWindow32()) 
833         {
834             WINPOS_ChangeActiveWindow( hwnd, FALSE );
835             KEYBOARD_UpdateState();
836         }
837         if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
838             SetFocus32( hwnd );
839     }
840 }
841
842
843 /**********************************************************************
844  *              EVENT_FocusOut
845  *
846  * Note: only top-level override-redirect windows get FocusOut events.
847  */
848 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
849 {
850     if (event->detail != NotifyPointer)
851     {
852         HWND32  hwnd = pWnd->hwndSelf;
853
854         if (hwnd == GetActiveWindow32()) 
855             WINPOS_ChangeActiveWindow( 0, FALSE );
856         if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
857             SetFocus32( 0 );
858     }
859 }
860
861 /**********************************************************************
862  *              EVENT_CheckFocus
863  */
864 BOOL32 EVENT_CheckFocus(void)
865 {
866     WND*   pWnd;
867     Window xW;
868     int    state;
869
870     TSXGetInputFocus(display, &xW, &state);
871     if( xW == None ||
872         TSXFindContext(display, xW, winContext, (char **)&pWnd) ) 
873         return FALSE;
874     return TRUE;
875 }
876
877
878 /**********************************************************************
879  *              EVENT_GetGeometry
880  *
881  * Helper function for ConfigureNotify handling.
882  * Get the new geometry of a window relative to the root window.
883  */
884 static void EVENT_GetGeometry( Window win, int *px, int *py,
885                                unsigned int *pwidth, unsigned int *pheight )
886 {
887     Window root, parent, *children;
888     int xpos, ypos;
889     unsigned int width, height, border, depth, nb_children;
890
891     if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
892                        &border, &depth )) return;
893     if (win == rootWindow)
894     {
895         *px = *py = 0;
896         return;
897     }
898
899     for (;;)
900     {
901         if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
902             return;
903         TSXFree( children );
904         if (parent == rootWindow) break;
905         win = parent;
906         if (!TSXGetGeometry( display, win, &root, &xpos, &ypos,
907                            &width, &height, &border, &depth )) return;
908         *px += xpos;
909         *py += ypos;
910     }
911 }
912
913
914 /**********************************************************************
915  *              EVENT_ConfigureNotify
916  *
917  * The ConfigureNotify event is only selected on top-level windows
918  * when the -managed flag is used.
919  */
920 static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
921 {
922     WINDOWPOS32 winpos;
923     RECT32 newWindowRect, newClientRect;
924     HRGN32 hrgnOldPos, hrgnNewPos;
925     Window above = event->above;
926     int x, y;
927     unsigned int width, height;
928
929     assert (pWnd->flags & WIN_MANAGED);
930
931     /* We don't rely on the event geometry info, because it is relative
932      * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
933      * if the window hasn't moved).
934      */
935     EVENT_GetGeometry( event->window, &x, &y, &width, &height );
936
937     /* Fill WINDOWPOS struct */
938     winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
939     winpos.hwnd = pWnd->hwndSelf;
940     winpos.x = x;
941     winpos.y = y;
942     winpos.cx = width;
943     winpos.cy = height;
944
945     /* Check for unchanged attributes */
946     if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top)
947         winpos.flags |= SWP_NOMOVE;
948     if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) &&
949         (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top))
950         winpos.flags |= SWP_NOSIZE;
951     else
952     {
953         RECT32 rect = { 0, 0, pWnd->rectWindow.right - pWnd->rectWindow.left,
954                         pWnd->rectWindow.bottom - pWnd->rectWindow.top };
955         DCE_InvalidateDCE( pWnd, &rect );
956     }
957
958     /* Send WM_WINDOWPOSCHANGING */
959     SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
960
961     /* Calculate new position and size */
962     newWindowRect.left = x;
963     newWindowRect.right = x + width;
964     newWindowRect.top = y;
965     newWindowRect.bottom = y + height;
966
967     WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
968                            &pWnd->rectWindow, &pWnd->rectClient,
969                            &winpos, &newClientRect );
970
971     hrgnOldPos = CreateRectRgnIndirect32( &pWnd->rectWindow );
972     hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect );
973     CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
974     DeleteObject32(hrgnOldPos);
975     DeleteObject32(hrgnNewPos);
976  
977     /* Set new size and position */
978     pWnd->rectWindow = newWindowRect;
979     pWnd->rectClient = newClientRect;
980     SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
981
982     if (!IsWindow32( winpos.hwnd )) return;
983     if( above == None )                 /* absolute bottom */
984     {
985         WIN_UnlinkWindow( winpos.hwnd );
986         WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM);
987     }
988     else EVENT_QueryZOrder( pWnd );     /* try to outsmart window manager */
989 }
990
991
992 /***********************************************************************
993  *           EVENT_SelectionRequest
994  */
995 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
996 {
997     XSelectionEvent result;
998     Atom            rprop = None;
999     Window          request = event->requestor;
1000
1001     if(event->target == XA_STRING)
1002     {
1003         HANDLE16 hText;
1004         LPSTR  text;
1005         int    size,i,j;
1006
1007         rprop = event->property;
1008
1009         if(rprop == None) rprop = event->target;
1010
1011         if(event->selection!=XA_PRIMARY) rprop = None;
1012         else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
1013         else
1014         {
1015             /* open to make sure that clipboard is available */
1016
1017             BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
1018             char* lpstr = 0;
1019
1020             hText = GetClipboardData16(CF_TEXT);
1021             text = GlobalLock16(hText);
1022             size = GlobalSize16(hText);
1023
1024             /* remove carriage returns */
1025
1026             lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
1027             for(i=0,j=0; i < size && text[i]; i++ )
1028             {
1029                if( text[i] == '\r' && 
1030                   (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1031                lpstr[j++] = text[i];
1032             }
1033             lpstr[j]='\0';
1034
1035             TSXChangeProperty(display, request, rprop, 
1036                             XA_STRING, 8, PropModeReplace, 
1037                             lpstr, j);
1038             HeapFree( GetProcessHeap(), 0, lpstr );
1039
1040             /* close only if we opened before */
1041
1042             if(couldOpen) CloseClipboard32();
1043         }
1044     }
1045
1046     if(rprop == None) 
1047        TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target));
1048
1049     result.type = SelectionNotify;
1050     result.display = display;
1051     result.requestor = request;
1052     result.selection = event->selection;
1053     result.property = rprop;
1054     result.target = event->target;
1055     result.time = event->time;
1056     TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1057 }
1058
1059
1060 /***********************************************************************
1061  *           EVENT_SelectionNotify
1062  */
1063 static void EVENT_SelectionNotify( XSelectionEvent *event )
1064 {
1065     if (event->selection != XA_PRIMARY) return;
1066
1067     if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
1068     else CLIPBOARD_ReadSelection( event->requestor, event->property );
1069
1070     TRACE(clipboard,"\tSelectionNotify done!\n");
1071 }
1072
1073
1074 /***********************************************************************
1075  *           EVENT_SelectionClear
1076  */
1077 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
1078 {
1079     if (event->selection != XA_PRIMARY) return;
1080     CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); 
1081 }
1082
1083
1084 /**********************************************************************
1085  *           EVENT_DropFromOffix
1086  *
1087  * don't know if it still works (last Changlog is from 96/11/04)
1088  */
1089 static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event )
1090 {
1091   unsigned long         data_length;
1092   unsigned long         aux_long;
1093   unsigned char*        p_data = NULL;
1094   union {
1095     Atom                atom_aux;
1096     POINT32     pt_aux;
1097     int         i;
1098   }             u;
1099   int                   x, y;
1100   BOOL16                bAccept;
1101   HGLOBAL16             hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
1102   LPDRAGINFO            lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1103   SEGPTR                spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
1104   Window                w_aux_root, w_aux_child;
1105   WND*                  pDropWnd;
1106   
1107   if( !lpDragInfo || !spDragInfo ) return;
1108   
1109   TSXQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child, 
1110                    &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
1111   
1112   lpDragInfo->hScope = pWnd->hwndSelf;
1113   lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1114   
1115   /* find out drop point and drop window */
1116   if( x < 0 || y < 0 ||
1117       x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1118       y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1119     {   bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1120   else
1121     {
1122       bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
1123       x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1124     }
1125   pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1126   GlobalFree16( hDragInfo );
1127   
1128   if( bAccept )
1129     {
1130       TSXGetWindowProperty( display, DefaultRootWindow(display),
1131                             dndSelection, 0, 65535, FALSE,
1132                             AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
1133                             &data_length, &aux_long, &p_data);
1134       
1135       if( !aux_long && p_data)  /* don't bother if > 64K */
1136         {
1137           char *p = (char*) p_data;
1138           char *p_drop;
1139           
1140           aux_long = 0; 
1141           while( *p )   /* calculate buffer size */
1142             {
1143               p_drop = p;
1144               if((u.i = *p) != -1 ) 
1145                 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
1146               if( u.i == -1 ) *p = -1;  /* mark as "bad" */
1147               else
1148                 {
1149                   INT32 len = GetShortPathName32A( p, NULL, 0 );
1150                   if (len) aux_long += len + 1;
1151                   else *p = -1;
1152                 }
1153               p += strlen(p) + 1;
1154             }
1155           if( aux_long && aux_long < 65535 )
1156             {
1157               HDROP16                 hDrop;
1158               LPDROPFILESTRUCT16        lpDrop;
1159               
1160               aux_long += sizeof(DROPFILESTRUCT16) + 1; 
1161               hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
1162               lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop );
1163               
1164               if( lpDrop )
1165                 {
1166                   lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1167                   lpDrop->ptMousePos.x = (INT16)x;
1168                   lpDrop->ptMousePos.y = (INT16)y;
1169                   lpDrop->fInNonClientArea = (BOOL16) 
1170                     ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1171                       y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1172                       x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1173                       y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1174                   p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1175                   p = p_data;
1176                   while(*p)
1177                     {
1178                       if( *p != -1 )    /* use only "good" entries */
1179                         {
1180                           GetShortPathName32A( p, p_drop, 65535 );
1181                           p_drop += strlen( p_drop ) + 1;
1182                         }
1183                       p += strlen(p) + 1;
1184                     }
1185                   *p_drop = '\0';
1186                   PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
1187                                  (WPARAM16)hDrop, 0L );
1188                 }
1189             }
1190         }
1191       if( p_data ) TSXFree(p_data);  
1192       
1193     } /* WS_EX_ACCEPTFILES */
1194 }
1195
1196 /**********************************************************************
1197  *           EVENT_DropURLs
1198  *
1199  * drop items are separated by \n 
1200  * each item is prefixed by its mime type
1201  *
1202  * event->data.l[3], event->data.l[4] contains drop x,y position
1203  */
1204 static void EVENT_DropURLs( WND *pWnd, XClientMessageEvent *event )
1205 {
1206   WND           *pDropWnd;
1207   unsigned long data_length;
1208   unsigned long aux_long, drop_len = 0;
1209   unsigned char *p_data = NULL; /* property data */
1210   char          *p_drop = NULL;
1211   char          *p, *next;
1212   int           x, y, drop32 = FALSE ;
1213   union {
1214     Atom        atom_aux;
1215     POINT32     pt_aux;
1216     int         i;
1217     Window      w_aux;
1218   }             u; /* unused */
1219   union {
1220     HDROP16     h16;
1221     HDROP32     h32;
1222   } hDrop;
1223
1224   drop32 = pWnd->flags & WIN_ISWIN32;
1225
1226   if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
1227     return;
1228
1229   TSXGetWindowProperty( display, DefaultRootWindow(display),
1230                         dndSelection, 0, 65535, FALSE,
1231                         AnyPropertyType, &u.atom_aux, &u.i,
1232                         &data_length, &aux_long, &p_data);
1233   if (aux_long)
1234     WARN(event,"property too large, truncated!\n");
1235   TRACE(event,"urls=%s\n", p_data);
1236
1237   if( !aux_long && p_data) {    /* don't bother if > 64K */
1238     /* calculate length */
1239     p = p_data;
1240     next = strchr(p, '\n');
1241     while (p) {
1242       if (next) *next=0;
1243       if (strncmp(p,"file:",5) == 0 ) {
1244         INT32 len = GetShortPathName32A( p+5, NULL, 0 );
1245         if (len) drop_len += len + 1;
1246       }
1247       if (next) { 
1248         *next = '\n'; 
1249         p = next + 1;
1250         next = strchr(p, '\n');
1251       } else {
1252         p = NULL;
1253       }
1254     }
1255     
1256     if( drop_len && drop_len < 65535 ) {
1257       TSXQueryPointer( display, rootWindow, &u.w_aux, &u.w_aux, 
1258                        &x, &y, &u.i, &u.i, &u.i);
1259       pDropWnd = WIN_FindWndPtr( pWnd->hwndSelf );
1260       
1261       if (drop32) {
1262         LPDROPFILESTRUCT32        lpDrop;
1263         drop_len += sizeof(DROPFILESTRUCT32) + 1; 
1264         hDrop.h32 = (HDROP32)GlobalAlloc32( GMEM_SHARE, drop_len );
1265         lpDrop = (LPDROPFILESTRUCT32) GlobalLock32( hDrop.h32 );
1266         
1267         if( lpDrop ) {
1268           lpDrop->lSize = sizeof(DROPFILESTRUCT32);
1269           lpDrop->ptMousePos.x = (INT32)x;
1270           lpDrop->ptMousePos.y = (INT32)y;
1271           lpDrop->fInNonClientArea = (BOOL32) 
1272             ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1273               y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1274               x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1275               y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1276           lpDrop->fWideChar = FALSE;
1277           p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT32);
1278         }
1279       } else {
1280         LPDROPFILESTRUCT16        lpDrop;
1281         drop_len += sizeof(DROPFILESTRUCT16) + 1; 
1282         hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len );
1283         lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 );
1284         
1285         if( lpDrop ) {
1286           lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1287           lpDrop->ptMousePos.x = (INT16)x;
1288           lpDrop->ptMousePos.y = (INT16)y;
1289           lpDrop->fInNonClientArea = (BOOL16) 
1290             ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1291               y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1292               x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1293               y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1294           p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1295         }
1296       }
1297       
1298       /* create message content */
1299       if (p_drop) {
1300         p = p_data;
1301         next = strchr(p, '\n');
1302         while (p) {
1303           if (next) *next=0;
1304           if (strncmp(p,"file:",5) == 0 ) {
1305             INT32 len = GetShortPathName32A( p+5, p_drop, 65535 );
1306             if (len) {
1307               TRACE(event, "drop file %s as %s\n", p+5, p_drop);
1308               p_drop += len+1;
1309             } else {
1310               WARN(event, "can't convert file %s to dos name \n", p+5);
1311             }
1312           } else {
1313             WARN(event, "unknown mime type %s\n", p);
1314           }
1315           if (next) { 
1316             *next = '\n'; 
1317             p = next + 1;
1318             next = strchr(p, '\n');
1319           } else {
1320             p = NULL;
1321           }
1322           *p_drop = '\0';
1323         }
1324
1325         if (drop32) {
1326           /* can not use PostMessage32A because it is currently based on 
1327            * PostMessage16 and WPARAM32 would be truncated to WPARAM16
1328            */
1329           GlobalUnlock32(hDrop.h32);
1330           SendMessage32A( pWnd->hwndSelf, WM_DROPFILES,
1331                           (WPARAM32)hDrop.h32, 0L );
1332         } else {
1333           GlobalUnlock16(hDrop.h16);
1334           PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
1335                          (WPARAM16)hDrop.h16, 0L );
1336         }
1337       }
1338     }
1339     if( p_data ) TSXFree(p_data);  
1340   }
1341 }
1342
1343 /**********************************************************************
1344  *           EVENT_ClientMessage
1345  */
1346 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
1347 {
1348     if (event->message_type != None && event->format == 32) {
1349       if ((event->message_type == wmProtocols) && 
1350           (((Atom) event->data.l[0]) == wmDeleteWindow))
1351         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
1352       else if ( event->message_type == dndProtocol &&
1353                 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
1354         EVENT_DropFromOffiX(pWnd, event);
1355       else if ( event->message_type == dndProtocol &&
1356                 event->data.l[0] == DndURL )
1357         EVENT_DropURLs(pWnd, event);
1358       else {
1359 #if 0
1360         /* enable this if you want to see the message */
1361         unsigned char* p_data = NULL;
1362         union {
1363           unsigned long l;
1364           int                   i;
1365           Atom          atom;
1366         } u; /* unused */
1367         TSXGetWindowProperty( display, DefaultRootWindow(display),
1368                               dndSelection, 0, 65535, FALSE,
1369                               AnyPropertyType, &u.atom, &u.i,
1370                               &u.l, &u.l, &p_data);
1371         TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1372               event->message_type, event->data.l[0], event->data.l[1], 
1373               event->data.l[2], event->data.l[3], event->data.l[4],
1374               p_data);
1375 #endif
1376         TRACE(event, "unrecognized ClientMessage\n" );
1377       }
1378     }
1379 }
1380
1381 /**********************************************************************
1382  *           EVENT_EnterNotify
1383  *
1384  * Install colormap when Wine window is focused in
1385  * self-managed mode with private colormap
1386  */
1387 /*
1388   void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1389   {
1390    if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1391      (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1392       TSXInstallColormap( display, COLOR_GetColormap() );
1393   }
1394  */ 
1395
1396 /**********************************************************************
1397  *              EVENT_MapNotify
1398  */
1399 void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
1400 {
1401     HWND32 hwndFocus = GetFocus32();
1402
1403     if (hwndFocus && IsChild32( hWnd, hwndFocus ))
1404       FOCUS_SetXFocus( (HWND32)hwndFocus );
1405
1406     return;
1407 }
1408