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