Release 970305
[wine/multimedia.git] / windows / event.c
blob86c312995184d648730d357e0b5e73ad133f7db7
1 /*
2 * X events handling functions
3 *
4 * Copyright 1993 Alexandre Julliard
5 *
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <stdio.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 <X11/Xlib.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
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 "message.h"
31 #include "module.h"
32 #include "options.h"
33 #include "queue.h"
34 #include "winpos.h"
35 #include "drive.h"
36 #include "shell.h"
37 #include "xmalloc.h"
38 #include "keyboard.h"
39 #include "stddebug.h"
40 #include "debug.h"
41 #include "dde_proc.h"
44 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
46 #define DndNotDnd -1 /* OffiX drag&drop */
47 #define DndUnknown 0
48 #define DndRawData 1
49 #define DndFile 2
50 #define DndFiles 3
51 #define DndText 4
52 #define DndDir 5
53 #define DndLink 6
54 #define DndExe 7
56 #define DndEND 8
58 /* X context to associate a hwnd to an X window */
59 static XContext winContext = 0;
61 static INT16 captureHT = HTCLIENT;
62 static HWND32 captureWnd = 0;
63 static BOOL32 InputEnabled = TRUE;
64 static BOOL32 SwappedButtons = FALSE;
66 static Atom wmProtocols = None;
67 static Atom wmDeleteWindow = None;
68 static Atom dndProtocol = None;
69 static Atom dndSelection = None;
71 static const char * const event_names[] =
73 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
74 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
75 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
76 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
77 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
78 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
79 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
80 "ClientMessage", "MappingNotify"
83 /* Event handlers */
84 static void EVENT_Key( XKeyEvent *event );
85 static void EVENT_ButtonPress( XButtonEvent *event );
86 static void EVENT_ButtonRelease( XButtonEvent *event );
87 static void EVENT_MotionNotify( XMotionEvent *event );
88 static void EVENT_FocusIn( HWND32 hwnd, XFocusChangeEvent *event );
89 static void EVENT_FocusOut( HWND32 hwnd, XFocusChangeEvent *event );
90 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
91 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
92 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event );
93 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
94 static void EVENT_SelectionNotify( XSelectionEvent *event);
95 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
96 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
97 static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
99 /* Usable only with OLVWM - compile option perhaps?
100 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
103 extern void FOCUS_SetXFocus( HWND32 );
104 extern BOOL16 DRAG_QueryUpdate( HWND16, SEGPTR, BOOL32 );
106 /***********************************************************************
107 * EVENT_ProcessEvent
109 * Process an X event.
111 void EVENT_ProcessEvent( XEvent *event )
113 WND *pWnd;
115 if (XFindContext( display, event->xany.window, winContext,
116 (char **)&pWnd ) != 0)
117 return; /* Not for a registered window */
119 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
120 event_names[event->type], pWnd->hwndSelf );
122 switch(event->type)
124 case KeyPress:
125 case KeyRelease:
126 if (InputEnabled)
127 EVENT_Key( (XKeyEvent*)event );
128 break;
130 case ButtonPress:
131 if (InputEnabled)
132 EVENT_ButtonPress( (XButtonEvent*)event );
133 break;
135 case ButtonRelease:
136 if (InputEnabled)
137 EVENT_ButtonRelease( (XButtonEvent*)event );
138 break;
140 case MotionNotify:
141 /* Wine between two fast machines across the overloaded campus
142 ethernet gets very boged down in MotionEvents. The following
143 simply finds the last motion event in the queue and drops
144 the rest. On a good link events are servered before they build
145 up so this doesn't take place. On a slow link this may cause
146 problems if the event order is important. I'm not yet seen
147 of any problems. Jon 7/6/96.
149 if (InputEnabled)
151 while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
152 MotionNotify, event));
153 EVENT_MotionNotify( (XMotionEvent*)event );
155 break;
157 case FocusIn:
158 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
159 break;
161 case FocusOut:
162 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
163 break;
165 case Expose:
166 EVENT_Expose( pWnd, (XExposeEvent *)event );
167 break;
169 case GraphicsExpose:
170 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
171 break;
173 case ConfigureNotify:
174 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
175 break;
177 case SelectionRequest:
178 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
179 break;
181 case SelectionNotify:
182 EVENT_SelectionNotify( (XSelectionEvent *)event );
183 break;
185 case SelectionClear:
186 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
187 break;
189 case ClientMessage:
190 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
191 break;
193 /* case EnterNotify:
194 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
195 * break;
197 case NoExpose:
198 break;
200 /* We get all these because of StructureNotifyMask. */
201 case UnmapNotify:
202 case CirculateNotify:
203 case CreateNotify:
204 case DestroyNotify:
205 case GravityNotify:
206 case ReparentNotify:
207 break;
209 case MapNotify:
210 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
211 break;
213 default:
214 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
215 event_names[event->type], pWnd->hwndSelf );
216 break;
221 /***********************************************************************
222 * EVENT_RegisterWindow
224 * Associate an X window to a HWND.
226 void EVENT_RegisterWindow( WND *pWnd )
228 if (wmProtocols == None)
229 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
230 if (wmDeleteWindow == None)
231 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
232 if( dndProtocol == None )
233 dndProtocol = XInternAtom( display, "DndProtocol" , False );
234 if( dndSelection == None )
235 dndSelection = XInternAtom( display, "DndSelection" , False );
237 XSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
239 if (!winContext) winContext = XUniqueContext();
240 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
243 /***********************************************************************
244 * EVENT_DestroyWindow
246 void EVENT_DestroyWindow( WND *pWnd )
248 XEvent xe;
250 XDeleteContext( display, pWnd->window, winContext );
251 XDestroyWindow( display, pWnd->window );
252 while( XCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
255 /***********************************************************************
256 * EVENT_WaitXEvent
258 * Wait for an X event, optionally sleeping until one arrives.
259 * Return TRUE if an event is pending, FALSE on timeout or error
260 * (for instance lost connection with the server).
262 BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek )
264 XEvent event;
265 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
267 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
268 * in this case, we fall through directly to the XNextEvent loop.
271 if ((maxWait != -1) && !XPending(display))
273 fd_set read_set;
274 struct timeval timeout;
275 int fd = ConnectionNumber(display);
277 FD_ZERO( &read_set );
278 FD_SET( fd, &read_set );
280 timeout.tv_usec = (maxWait % 1000) * 1000;
281 timeout.tv_sec = maxWait / 1000;
283 #ifdef CONFIG_IPC
284 sigsetjmp(env_wait_x, 1);
285 stop_wait_op= CONT;
287 if (DDE_GetRemoteMessage()) {
288 while(DDE_GetRemoteMessage())
290 return TRUE;
292 stop_wait_op = STOP_WAIT_X;
293 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
294 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
295 !XPending(display))
297 stop_wait_op = CONT;
298 TIMER_ExpireTimers();
299 return FALSE;
301 else stop_wait_op = CONT;
302 #else /* CONFIG_IPC */
303 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
305 /* Timeout or error */
306 TIMER_ExpireTimers();
307 return FALSE;
309 #endif /* CONFIG_IPC */
313 /* Process the event (and possibly others that occurred in the meantime) */
318 #ifdef CONFIG_IPC
319 if (DDE_GetRemoteMessage())
321 while(DDE_GetRemoteMessage()) ;
322 return TRUE;
324 #endif /* CONFIG_IPC */
326 XNextEvent( display, &event );
328 if( peek )
330 WND* pWnd;
331 MESSAGEQUEUE* pQ;
333 if (XFindContext( display, ((XAnyEvent *)&event)->window, winContext,
334 (char **)&pWnd ) || (event.type == NoExpose))
335 continue;
337 /* Check only for those events which can be processed
338 * internally. */
340 if( event.type == MotionNotify ||
341 event.type == ButtonPress || event.type == ButtonRelease ||
342 event.type == KeyPress || event.type == KeyRelease ||
343 event.type == SelectionRequest || event.type == SelectionClear )
345 EVENT_ProcessEvent( &event );
346 continue;
349 if( pWnd )
350 if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
352 pQ->flags |= QUEUE_FLAG_XEVENT;
353 PostEvent(pQ->hTask);
354 XPutBackEvent(display, &event);
355 break;
358 else
359 EVENT_ProcessEvent( &event );
361 while (XPending( display ));
362 return TRUE;
366 /***********************************************************************
367 * EVENT_Synchronize
369 * Synchronize with the X server. Should not be used too often.
371 void EVENT_Synchronize()
373 XEvent event;
375 XSync( display, False );
376 while (XPending( display ))
378 XNextEvent( display, &event );
379 EVENT_ProcessEvent( &event );
384 /***********************************************************************
385 * EVENT_XStateToKeyState
387 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
388 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
390 static WORD EVENT_XStateToKeyState( int state )
392 int kstate = 0;
394 if (state & Button1Mask) kstate |= MK_LBUTTON;
395 if (state & Button2Mask) kstate |= MK_MBUTTON;
396 if (state & Button3Mask) kstate |= MK_RBUTTON;
397 if (state & ShiftMask) kstate |= MK_SHIFT;
398 if (state & ControlMask) kstate |= MK_CONTROL;
399 return kstate;
403 /***********************************************************************
404 * EVENT_Expose
406 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
408 RECT32 rect;
410 /* Make position relative to client area instead of window */
411 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
412 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
413 rect.right = rect.left + event->width;
414 rect.bottom = rect.top + event->height;
416 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
417 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
418 (event->count ? 0 : RDW_ERASENOW), 0 );
422 /***********************************************************************
423 * EVENT_GraphicsExpose
425 * This is needed when scrolling area is partially obscured
426 * by non-Wine X window.
428 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
430 RECT32 rect;
432 /* Make position relative to client area instead of window */
433 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
434 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
435 rect.right = rect.left + event->width;
436 rect.bottom = rect.top + event->height;
438 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
439 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
440 (event->count ? 0 : RDW_ERASENOW), 0 );
444 /***********************************************************************
445 * EVENT_Key
447 * Handle a X key event
449 static void EVENT_Key( XKeyEvent *event )
451 KEYBOARD_HandleEvent( event );
455 /***********************************************************************
456 * EVENT_MotionNotify
458 static void EVENT_MotionNotify( XMotionEvent *event )
460 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
461 event->x_root - desktopX, event->y_root - desktopY,
462 event->time - MSG_WineStartTicks, 0 );
466 /***********************************************************************
467 * EVENT_DummyMotionNotify
469 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
471 void EVENT_DummyMotionNotify(void)
473 Window root, child;
474 int rootX, rootY, childX, childY;
475 unsigned int state;
477 if (XQueryPointer( display, rootWindow, &root, &child,
478 &rootX, &rootY, &childX, &childY, &state ))
480 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
481 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
486 /***********************************************************************
487 * EVENT_ButtonPress
489 static void EVENT_ButtonPress( XButtonEvent *event )
491 static WORD messages[NB_BUTTONS] =
492 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
493 int buttonNum = event->button - 1;
495 if (buttonNum >= NB_BUTTONS) return;
496 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
497 MouseButtonsStates[buttonNum] = 0x8000;
498 AsyncMouseButtonsStates[buttonNum] = 0x8000;
499 hardware_event( messages[buttonNum],
500 EVENT_XStateToKeyState( event->state ), 0L,
501 event->x_root - desktopX, event->y_root - desktopY,
502 event->time - MSG_WineStartTicks, 0 );
506 /***********************************************************************
507 * EVENT_ButtonRelease
509 static void EVENT_ButtonRelease( XButtonEvent *event )
511 static const WORD messages[NB_BUTTONS] =
512 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
513 int buttonNum = event->button - 1;
515 if (buttonNum >= NB_BUTTONS) return;
516 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
517 MouseButtonsStates[buttonNum] = FALSE;
518 hardware_event( messages[buttonNum],
519 EVENT_XStateToKeyState( event->state ), 0L,
520 event->x_root - desktopX, event->y_root - desktopY,
521 event->time - MSG_WineStartTicks, 0 );
525 /**********************************************************************
526 * EVENT_FocusIn
528 static void EVENT_FocusIn( HWND32 hwnd, XFocusChangeEvent *event )
530 if (event->detail == NotifyPointer) return;
531 if (hwnd != GetActiveWindow32()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
532 if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
533 SetFocus32( hwnd );
537 /**********************************************************************
538 * EVENT_FocusOut
540 * Note: only top-level override-redirect windows get FocusOut events.
542 static void EVENT_FocusOut( HWND32 hwnd, XFocusChangeEvent *event )
544 if (event->detail == NotifyPointer) return;
545 if (hwnd == GetActiveWindow32()) WINPOS_ChangeActiveWindow( 0, FALSE );
546 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
547 SetFocus32( 0 );
550 /**********************************************************************
551 * EVENT_CheckFocus
553 BOOL32 EVENT_CheckFocus(void)
555 WND* pWnd;
556 Window xW;
557 int state;
559 XGetInputFocus(display, &xW, &state);
560 if( xW == None ||
561 XFindContext(display, xW, winContext, (char **)&pWnd) )
562 return FALSE;
563 return TRUE;
566 /**********************************************************************
567 * EVENT_ConfigureNotify
569 * The ConfigureNotify event is only selected on the desktop window
570 * and on top-level windows when the -managed flag is used.
572 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event )
574 /* FIXME: with -desktop xxx we get this event _before_ desktop
575 * window structure is created. WIN_GetDesktop() check is a hack.
578 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
580 desktopX = event->x;
581 desktopY = event->y;
583 else
585 WND *wndPtr;
586 WINDOWPOS16 *winpos;
587 RECT16 newWindowRect, newClientRect;
588 HRGN32 hrgnOldPos, hrgnNewPos;
590 if (!(wndPtr = WIN_FindWndPtr( hwnd )) ||
591 !(wndPtr->flags & WIN_MANAGED) )
592 return;
594 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
596 /* Fill WINDOWPOS struct */
597 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
598 winpos->hwnd = hwnd;
599 winpos->x = event->x;
600 winpos->y = event->y;
601 winpos->cx = event->width;
602 winpos->cy = event->height;
604 /* Check for unchanged attributes */
605 if(winpos->x == wndPtr->rectWindow.left &&
606 winpos->y == wndPtr->rectWindow.top)
607 winpos->flags |= SWP_NOMOVE;
608 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
609 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
610 winpos->flags |= SWP_NOSIZE;
612 /* Send WM_WINDOWPOSCHANGING */
613 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
615 /* Calculate new position and size */
616 newWindowRect.left = event->x;
617 newWindowRect.right = event->x + event->width;
618 newWindowRect.top = event->y;
619 newWindowRect.bottom = event->y + event->height;
621 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
622 &wndPtr->rectWindow, &wndPtr->rectClient,
623 SEGPTR_GET(winpos), &newClientRect );
625 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
626 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
627 CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
629 /* Set new size and position */
630 wndPtr->rectWindow = newWindowRect;
631 wndPtr->rectClient = newClientRect;
632 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
633 SEGPTR_FREE(winpos);
635 /* full window drag leaves unrepainted garbage without this */
636 PAINT_RedrawWindow( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
637 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW,
638 RDW_C_USEHRGN );
639 DeleteObject32(hrgnOldPos);
640 DeleteObject32(hrgnNewPos);
645 /***********************************************************************
646 * EVENT_SelectionRequest
648 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
650 XSelectionEvent result;
651 Atom rprop = None;
652 Window request = event->requestor;
654 if(event->target == XA_STRING)
656 HANDLE16 hText;
657 LPSTR text;
658 int size,i,j;
660 rprop = event->property;
662 if(rprop == None) rprop = event->target;
664 if(event->selection!=XA_PRIMARY) rprop = None;
665 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
666 else
668 /* open to make sure that clipboard is available */
670 BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
671 char* lpstr = 0;
673 hText = GetClipboardData16(CF_TEXT);
674 text = GlobalLock16(hText);
675 size = GlobalSize16(hText);
677 /* remove carriage returns */
679 lpstr = (char*)xmalloc(size--);
680 for(i=0,j=0; i < size && text[i]; i++ )
682 if( text[i] == '\r' &&
683 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
684 lpstr[j++] = text[i];
686 lpstr[j]='\0';
688 XChangeProperty(display, request, rprop,
689 XA_STRING, 8, PropModeReplace,
690 lpstr, j);
691 free(lpstr);
693 /* close only if we opened before */
695 if(couldOpen) CloseClipboard32();
699 if(rprop==None)
700 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
702 result.type=SelectionNotify;
703 result.display=display;
704 result.requestor=request;
705 result.selection=event->selection;
706 result.property=rprop;
707 result.target=event->target;
708 result.time=event->time;
709 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
713 /***********************************************************************
714 * EVENT_SelectionNotify
716 static void EVENT_SelectionNotify( XSelectionEvent *event )
718 if (event->selection != XA_PRIMARY) return;
720 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
721 else CLIPBOARD_ReadSelection( event->requestor, event->property );
723 dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
727 /***********************************************************************
728 * EVENT_SelectionClear
730 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
732 if (event->selection != XA_PRIMARY) return;
733 CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf );
737 /**********************************************************************
738 * EVENT_ClientMessage
740 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
742 if (event->message_type != None && event->format == 32)
744 if ((event->message_type == wmProtocols) &&
745 (((Atom) event->data.l[0]) == wmDeleteWindow))
746 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
747 else if ( event->message_type == dndProtocol &&
748 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
750 unsigned long data_length;
751 unsigned long aux_long;
752 unsigned char* p_data = NULL;
753 union {
754 Atom atom_aux;
755 POINT32 pt_aux;
756 int i;
757 } u;
758 int x, y;
759 BOOL16 bAccept;
760 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
761 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
762 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
763 Window w_aux_root, w_aux_child;
764 WND* pDropWnd;
766 if( !lpDragInfo || !spDragInfo ) return;
768 XQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child,
769 &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
771 lpDragInfo->hScope = pWnd->hwndSelf;
772 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
774 /* find out drop point and drop window */
775 if( x < 0 || y < 0 ||
776 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
777 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
778 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
779 else
781 bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
782 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
784 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
785 GlobalFree16( hDragInfo );
787 if( bAccept )
789 XGetWindowProperty( display, DefaultRootWindow(display),
790 dndSelection, 0, 65535, FALSE,
791 AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
792 &data_length, &aux_long, &p_data);
794 if( !aux_long && p_data) /* don't bother if > 64K */
796 char *p = (char*) p_data;
797 char *p_drop;
799 aux_long = 0;
800 while( *p ) /* calculate buffer size */
802 p_drop = p;
803 if((u.i = *p) != -1 )
804 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
805 if( u.i == -1 ) *p = -1; /* mark as "bad" */
806 else
808 INT32 len = GetShortPathName32A( p, NULL, 0 );
809 if (len) aux_long += len + 1;
810 else *p = -1;
812 p += strlen(p) + 1;
814 if( aux_long && aux_long < 65535 )
816 HDROP16 hDrop;
817 LPDROPFILESTRUCT lpDrop;
819 aux_long += sizeof(DROPFILESTRUCT) + 1;
820 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
821 lpDrop = (LPDROPFILESTRUCT) GlobalLock16( hDrop );
823 if( lpDrop )
825 lpDrop->wSize = sizeof(DROPFILESTRUCT);
826 lpDrop->ptMousePos.x = (INT16)x;
827 lpDrop->ptMousePos.y = (INT16)y;
828 lpDrop->fInNonClientArea = (BOOL16)
829 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
830 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
831 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
832 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
833 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
834 p = p_data;
835 while(*p)
837 if( *p != -1 ) /* use only "good" entries */
839 GetShortPathName32A( p, p_drop, 65535 );
840 p_drop += strlen( p_drop ) + 1;
842 p += strlen(p) + 1;
844 *p_drop = '\0';
845 PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
846 (WPARAM16)hDrop, 0L );
850 if( p_data ) XFree(p_data);
852 } /* WS_EX_ACCEPTFILES */
853 } /* dndProtocol */
854 else
855 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
859 /**********************************************************************
860 * EVENT_EnterNotify
862 * Install colormap when Wine window is focused in
863 * self-managed mode with private colormap
866 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
868 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
869 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
870 XInstallColormap( display, COLOR_GetColormap() );
874 /**********************************************************************
875 * EVENT_MapNotify
877 void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
879 HWND32 hwndFocus = GetFocus32();
881 if (hwndFocus && IsChild32( hWnd, hwndFocus ))
882 FOCUS_SetXFocus( (HWND32)hwndFocus );
884 return;
887 /**********************************************************************
888 * EVENT_Capture
890 * We need this to be able to generate double click messages
891 * when menu code captures mouse in the window without CS_DBLCLK style.
893 HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
895 Window win;
896 HWND32 capturePrev = captureWnd;
898 if (!hwnd)
900 XUngrabPointer(display, CurrentTime );
901 captureWnd = NULL; captureHT = 0;
903 else if ((win = WIN_GetXWindow( hwnd )))
905 WND* wndPtr = WIN_FindWndPtr( hwnd );
907 if ( wndPtr &&
908 (XGrabPointer(display, win, False,
909 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
910 GrabModeAsync, GrabModeAsync,
911 None, None, CurrentTime ) == GrabSuccess) )
913 dprintf_win(stddeb, "SetCapture(0x%04x)\n", hwnd );
914 captureWnd = hwnd;
915 captureHT = ht;
919 if( capturePrev && capturePrev != captureWnd )
921 WND* wndPtr = WIN_FindWndPtr( capturePrev );
922 if( wndPtr && (wndPtr->flags & WIN_ISWIN32) )
923 SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
925 return capturePrev;
928 /**********************************************************************
929 * EVENT_GetCaptureInfo
931 INT16 EVENT_GetCaptureInfo()
933 return captureHT;
936 /**********************************************************************
937 * SetCapture16 (USER.18)
939 HWND16 SetCapture16( HWND16 hwnd )
941 return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
945 /**********************************************************************
946 * SetCapture32 (USER32.463)
948 HWND32 SetCapture32( HWND32 hwnd )
950 return EVENT_Capture( hwnd, HTCLIENT );
954 /**********************************************************************
955 * ReleaseCapture (USER.19) (USER32.438)
957 void ReleaseCapture(void)
959 dprintf_win(stddeb, "ReleaseCapture() [%04x]\n", captureWnd );
960 if( captureWnd ) EVENT_Capture( 0, 0 );
964 /**********************************************************************
965 * GetCapture16 (USER.236)
967 HWND16 GetCapture16(void)
969 return captureWnd;
973 /**********************************************************************
974 * GetCapture32 (USER32.207)
976 HWND32 GetCapture32(void)
978 return captureWnd;
982 /***********************************************************************
983 * GetMouseEventProc (USER.337)
985 FARPROC16 GetMouseEventProc(void)
987 HMODULE16 hmodule = GetModuleHandle16("USER");
988 return MODULE_GetEntryPoint( hmodule,
989 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
993 /***********************************************************************
994 * Mouse_Event (USER.299)
996 void Mouse_Event( CONTEXT *context )
998 /* Register values:
999 * AX = mouse event
1000 * BX = horizontal displacement if AX & ME_MOVE
1001 * CX = vertical displacement if AX & ME_MOVE
1002 * DX = button state (?)
1003 * SI = mouse event flags (?)
1005 Window root, child;
1006 int rootX, rootY, childX, childY;
1007 unsigned int state;
1009 if (AX_reg(context) & ME_MOVE)
1011 /* We have to actually move the cursor */
1012 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
1013 (short)BX_reg(context), (short)CX_reg(context) );
1014 return;
1016 if (!XQueryPointer( display, rootWindow, &root, &child,
1017 &rootX, &rootY, &childX, &childY, &state )) return;
1018 if (AX_reg(context) & ME_LDOWN)
1019 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1020 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1021 if (AX_reg(context) & ME_LUP)
1022 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1023 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1024 if (AX_reg(context) & ME_RDOWN)
1025 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1026 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1027 if (AX_reg(context) & ME_RUP)
1028 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1029 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1033 /**********************************************************************
1034 * EnableHardwareInput (USER.331)
1036 BOOL16 EnableHardwareInput(BOOL16 bEnable)
1038 BOOL16 bOldState = InputEnabled;
1039 dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
1040 InputEnabled = bEnable;
1041 return bOldState;
1045 /***********************************************************************
1046 * SwapMouseButton16 (USER.186)
1048 BOOL16 SwapMouseButton16( BOOL16 fSwap )
1050 BOOL16 ret = SwappedButtons;
1051 SwappedButtons = fSwap;
1052 return ret;
1056 /***********************************************************************
1057 * SwapMouseButton32 (USER32.536)
1059 BOOL32 SwapMouseButton32( BOOL32 fSwap )
1061 BOOL32 ret = SwappedButtons;
1062 SwappedButtons = fSwap;
1063 return ret;