2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
13 #include <sys/types.h>
15 #include <X11/keysym.h>
17 #include <X11/Xresource.h>
18 #include <X11/Xutil.h>
19 #include <X11/Xatom.h>
26 #include "clipboard.h"
32 #include "registers.h"
40 typedef char *XPointer;
44 #ifdef WHO_NEEDS_DIRTY_HACKS
46 /* Dirty hack to compile with Sun's OpenWindows */
47 typedef char *XPointer;
51 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
53 /* X context to associate a hwnd to an X window */
54 static XContext winContext = 0;
57 BOOL MouseButtonsStates[NB_BUTTONS];
58 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
59 BYTE KeyStateTable[256];
60 BYTE AsyncKeyStateTable[256];
63 WPARAM lastEventChar = 0; /* this will have to be changed once
64 * ToAscii starts working */
66 static HWND captureWnd = 0;
67 static BOOL InputEnabled = TRUE;
69 /* Keyboard translation tables */
70 static const int special_key[] =
72 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
73 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
74 0, 0, 0, VK_ESCAPE /* FF18 */
77 static const int cursor_key[] =
79 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
80 VK_NEXT, VK_END /* FF50 */
83 static const int misc_key[] =
85 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
86 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
89 static const int keypad_key[] =
91 VK_MENU, VK_NUMLOCK, /* FF7E */
92 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
93 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
94 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
95 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
96 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
97 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
98 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
99 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
100 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
101 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
104 static const int function_key[] =
106 VK_F1, VK_F2, /* FFBE */
107 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
108 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
111 static const int modifier_key[] =
113 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
115 0, VK_MENU, VK_MENU /* FFE8 */
122 unsigned long count : 16;
123 unsigned long code : 8;
124 unsigned long extended : 1;
126 unsigned long reserved : 2;
127 unsigned long context : 1;
128 unsigned long previous : 1;
129 unsigned long transition : 1;
134 static BOOL KeyDown = FALSE;
136 static const char * const event_names[] =
138 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
139 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
140 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
141 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
142 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
143 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
144 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
145 "ClientMessage", "MappingNotify"
149 static void EVENT_key( XKeyEvent *event );
150 static void EVENT_ButtonPress( XButtonEvent *event );
151 static void EVENT_ButtonRelease( XButtonEvent *event );
152 static void EVENT_MotionNotify( XMotionEvent *event );
153 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
154 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
155 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
156 static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event );
157 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
158 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
159 static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
160 static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
161 static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
164 /***********************************************************************
167 * Process an X event.
169 void EVENT_ProcessEvent( XEvent *event )
174 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
175 hwnd = (HWND) (int)ptr;
177 dprintf_event(stddeb, "Got event %s for hwnd %04x\n",
178 event_names[event->type], hwnd );
184 EVENT_key( (XKeyEvent*)event );
188 EVENT_ButtonPress( (XButtonEvent*)event );
192 EVENT_ButtonRelease( (XButtonEvent*)event );
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.
204 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
205 MotionNotify, event));
206 EVENT_MotionNotify( (XMotionEvent*)event );
210 EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
214 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
218 EVENT_Expose( hwnd, (XExposeEvent*)event );
221 case ConfigureNotify:
222 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
225 case SelectionRequest:
226 EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
229 case SelectionNotify:
230 EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
234 EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
238 EVENT_ClientMessage( hwnd, (XClientMessageEvent *) event );
242 EVENT_GraphicsExpose( hwnd, (XGraphicsExposeEvent *) event );
248 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
249 event_names[event->type], hwnd );
255 /***********************************************************************
256 * EVENT_RegisterWindow
258 * Associate an X window to a HWND.
260 void EVENT_RegisterWindow( Window w, HWND hwnd )
262 if (!winContext) winContext = XUniqueContext();
263 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
267 /***********************************************************************
270 * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
271 * Return TRUE if an event is pending, FALSE on timeout or error
272 * (for instance lost connection with the server).
274 BOOL EVENT_WaitXEvent( LONG maxWait )
277 struct timeval timeout;
279 int fd = ConnectionNumber(display);
281 if (!XPending(display) && (maxWait != -1))
283 FD_ZERO( &read_set );
284 FD_SET( fd, &read_set );
286 timeout.tv_usec = (maxWait % 1000) * 1000;
287 timeout.tv_sec = maxWait / 1000;
290 sigsetjmp(env_wait_x, 1);
293 if (DDE_GetRemoteMessage()) {
294 while(DDE_GetRemoteMessage())
298 stop_wait_op= STOP_WAIT_X;
299 /* The code up to the next "stop_wait_op= CONT" must be reentrant */
300 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
301 !XPending(display)) {
307 #else /* CONFIG_IPC */
308 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
309 return FALSE; /* Timeout or error */
310 #endif /* CONFIG_IPC */
314 /* Process the event (and possibly others that occurred in the meantime) */
319 if (DDE_GetRemoteMessage())
321 while(DDE_GetRemoteMessage()) ;
324 #endif /* CONFIG_IPC */
326 XNextEvent( display, &event );
327 EVENT_ProcessEvent( &event );
329 while (XPending( display ));
334 /***********************************************************************
337 * Synchronize with the X server. Should not be used too often.
339 void EVENT_Synchronize()
343 XSync( display, False );
344 while (XPending( display ))
346 XNextEvent( display, &event );
347 EVENT_ProcessEvent( &event );
352 /***********************************************************************
353 * EVENT_XStateToKeyState
355 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
356 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
358 static WORD EVENT_XStateToKeyState( int state )
362 if (state & Button1Mask) kstate |= MK_LBUTTON;
363 if (state & Button2Mask) kstate |= MK_MBUTTON;
364 if (state & Button3Mask) kstate |= MK_RBUTTON;
365 if (state & ShiftMask) kstate |= MK_SHIFT;
366 if (state & ControlMask) kstate |= MK_CONTROL;
371 /***********************************************************************
374 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
377 WND * wndPtr = WIN_FindWndPtr( hwnd );
380 /* Make position relative to client area instead of window */
381 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
382 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
383 rect.right = rect.left + event->width;
384 rect.bottom = rect.top + event->height;
386 RedrawWindow32( hwnd, &rect, 0,
387 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
388 (event->count ? 0 : RDW_ERASENOW) );
392 /***********************************************************************
393 * EVENT_GraphicsExpose
394 * This is needed when scrolling area is partially obscured
395 * by non-Wine X window.
397 static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event )
400 WND * wndPtr = WIN_FindWndPtr( hwnd );
403 /* Make position relative to client area instead of window */
404 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
405 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
406 rect.right = rect.left + event->width;
407 rect.bottom = rect.top + event->height;
409 RedrawWindow16( hwnd, &rect, 0,
410 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
411 (event->count ? 0 : RDW_ERASENOW) );
415 /***********************************************************************
418 * Handle a X key event
420 static void EVENT_key( XKeyEvent *event )
426 WORD xkey, key_type, key;
428 BOOL extended = FALSE;
430 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
432 Str[ascii_chars] = '\0';
433 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
434 keysym, ascii_chars, Str[0], Str);
436 /* Ctrl-Alt-Return enters the debugger */
437 if ((keysym == XK_Return) && (event->type == KeyPress) &&
438 (event->state & ControlMask) && (event->state & Mod1Mask))
439 DEBUG_EnterDebugger();
441 xkey = LOWORD(keysym);
442 key_type = HIBYTE(xkey);
444 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
446 if (key_type == 0xFF) /* non-character key */
448 if (key >= 0x08 && key <= 0x1B) /* special key */
449 vkey = special_key[key - 0x08];
450 else if (key >= 0x50 && key <= 0x57) /* cursor key */
451 vkey = cursor_key[key - 0x50];
452 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
453 vkey = misc_key[key - 0x60];
454 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
456 vkey = keypad_key[key - 0x7E];
459 else if (key >= 0xBE && key <= 0xCD) /* function key */
461 vkey = function_key[key - 0xBE];
464 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
465 vkey = modifier_key[key - 0xE1];
466 else if (key == 0xFF) /* DEL key */
469 else if (key_type == 0) /* character key */
472 vkey = toupper(key); /* convert lower to uppercase */
477 if (event->type == KeyPress)
479 if (!(KeyStateTable[vkey] & 0x80))
480 KeyStateTable[vkey] ^= 0x01;
481 KeyStateTable[vkey] |= 0x80;
483 keylp.lp1.code = LOBYTE(event->keycode) - 8;
484 keylp.lp1.extended = (extended ? 1 : 0);
485 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
486 keylp.lp1.context = ( (event->state & Mod1Mask) ||
487 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
488 keylp.lp1.previous = (KeyDown ? 0 : 1);
489 keylp.lp1.transition = 0;
490 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
492 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
493 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
495 event->x_root - desktopX, event->y_root - desktopY,
499 /* Currently we use reserved field in the scan-code byte to
500 * make it possible for TranslateMessage to recognize character keys
501 * and get them from lastEventChar global variable.
503 * ToAscii should handle it.
506 if( ascii_chars ) lastEventChar = Str[0];
510 UINT sysKey = KeyStateTable[VK_MENU];
512 KeyStateTable[vkey] &= ~0x80;
514 keylp.lp1.code = LOBYTE(event->keycode) - 8;
515 keylp.lp1.extended = (extended ? 1 : 0);
516 keylp.lp1.reserved = 0;
517 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
518 keylp.lp1.previous = 1;
519 keylp.lp1.transition = 1;
520 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
522 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
523 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
525 event->x_root - desktopX, event->y_root - desktopY,
532 /***********************************************************************
535 static void EVENT_MotionNotify( XMotionEvent *event )
537 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
538 event->x_root - desktopX, event->y_root - desktopY,
543 /***********************************************************************
544 * EVENT_DummyMotionNotify
546 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
548 void EVENT_DummyMotionNotify(void)
551 int rootX, rootY, childX, childY;
554 if (XQueryPointer( display, rootWindow, &root, &child,
555 &rootX, &rootY, &childX, &childY, &state ))
557 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
558 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
563 /***********************************************************************
566 static void EVENT_ButtonPress( XButtonEvent *event )
568 static WORD messages[NB_BUTTONS] =
569 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
570 int buttonNum = event->button - 1;
572 if (buttonNum >= NB_BUTTONS) return;
573 MouseButtonsStates[buttonNum] = 0x8000;
574 AsyncMouseButtonsStates[buttonNum] = 0x8000;
575 hardware_event( messages[buttonNum],
576 EVENT_XStateToKeyState( event->state ), 0L,
577 event->x_root - desktopX, event->y_root - desktopY,
582 /***********************************************************************
583 * EVENT_ButtonRelease
585 static void EVENT_ButtonRelease( XButtonEvent *event )
587 static const WORD messages[NB_BUTTONS] =
588 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
589 int buttonNum = event->button - 1;
591 if (buttonNum >= NB_BUTTONS) return;
592 MouseButtonsStates[buttonNum] = FALSE;
593 hardware_event( messages[buttonNum],
594 EVENT_XStateToKeyState( event->state ), 0L,
595 event->x_root - desktopX, event->y_root - desktopY,
600 /**********************************************************************
603 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
605 if (event->detail == NotifyPointer) return;
606 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
607 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
611 /**********************************************************************
614 * Note: only top-level override-redirect windows get FocusOut events.
616 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
618 if (event->detail == NotifyPointer) return;
619 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
620 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
624 /**********************************************************************
625 * EVENT_ConfigureNotify
627 * The ConfigureNotify event is only selected on the desktop window
628 * and on top-level windows when the -managed flag is used.
630 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
632 /* FIXME: with -desktop xxx we get this event _before_ desktop
633 * window structure is created. WIN_GetDesktop() check is a hack.
636 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
643 /* Managed window; most of this code is shamelessly
644 * stolen from SetWindowPos - FIXME: outdated
649 RECT16 newWindowRect, newClientRect;
650 HRGN hrgnOldPos, hrgnNewPos;
652 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
654 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
658 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
660 /* Artificial messages - what is this for? */
661 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
662 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
664 /* Fill WINDOWPOS struct */
665 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
667 winpos->x = event->x;
668 winpos->y = event->y;
669 winpos->cx = event->width;
670 winpos->cy = event->height;
672 /* Check for unchanged attributes */
673 if(winpos->x == wndPtr->rectWindow.left &&
674 winpos->y == wndPtr->rectWindow.top)
675 winpos->flags |= SWP_NOMOVE;
676 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
677 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
678 winpos->flags |= SWP_NOSIZE;
680 /* Send WM_WINDOWPOSCHANGING */
681 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
683 /* Calculate new position and size */
684 newWindowRect.left = event->x;
685 newWindowRect.right = event->x + event->width;
686 newWindowRect.top = event->y;
687 newWindowRect.bottom = event->y + event->height;
689 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
690 &wndPtr->rectWindow, &wndPtr->rectClient,
691 SEGPTR_GET(winpos), &newClientRect );
693 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
694 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
695 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
697 /* Set new size and position */
698 wndPtr->rectWindow = newWindowRect;
699 wndPtr->rectClient = newClientRect;
700 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
703 /* full window drag leaves unrepainted garbage without this */
704 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
705 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
706 DeleteObject(hrgnOldPos);
707 DeleteObject(hrgnNewPos);
712 /***********************************************************************
713 * EVENT_SelectionRequest
715 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
717 XSelectionEvent result;
719 Window request = event->requestor;
721 if(event->target == XA_STRING)
726 rprop = event->property;
728 if(rprop == None) rprop = event->target;
730 if(event->selection!=XA_PRIMARY) rprop = None;
731 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
733 /* Don't worry if we can't open */
734 BOOL couldOpen=OpenClipboard(hwnd);
735 hText=GetClipboardData(CF_TEXT);
736 text=GlobalLock16(hText);
737 XChangeProperty(display,request,rprop,XA_STRING,
738 8,PropModeReplace,text,strlen(text));
739 GlobalUnlock16(hText);
740 /* close only if we opened before */
741 if(couldOpen)CloseClipboard();
746 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
748 result.type=SelectionNotify;
749 result.display=display;
750 result.requestor=request;
751 result.selection=event->selection;
752 result.property=rprop;
753 result.target=event->target;
754 result.time=event->time;
755 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
759 /***********************************************************************
760 * EVENT_SelectionNotify
762 static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
764 if(event->selection!=XA_PRIMARY)return;
765 if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
766 CLIPBOARD_ReadSelection(event->requestor,event->property);
770 /***********************************************************************
771 * EVENT_SelectionClear
773 static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
775 if(event->selection!=XA_PRIMARY)return;
776 CLIPBOARD_ReleaseSelection(hwnd);
780 /**********************************************************************
781 * EVENT_ClientMessage
783 static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
785 static Atom wmProtocols = None;
786 static Atom wmDeleteWindow = None;
788 if (wmProtocols == None)
789 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
790 if (wmDeleteWindow == None)
791 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
793 if ((event->format != 32) || (event->message_type != wmProtocols) ||
794 (((Atom) event->data.l[0]) != wmDeleteWindow))
796 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
799 SendMessage16( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
803 /**********************************************************************
804 * SetCapture (USER.18)
806 HWND SetCapture( HWND hwnd )
809 HWND old_capture_wnd = captureWnd;
814 return old_capture_wnd;
816 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
817 if (XGrabPointer(display, win, False,
818 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
819 GrabModeAsync, GrabModeAsync,
820 None, None, CurrentTime ) == GrabSuccess)
822 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
824 return old_capture_wnd;
830 /**********************************************************************
831 * ReleaseCapture (USER.19)
833 void ReleaseCapture()
835 if (captureWnd == 0) return;
836 XUngrabPointer( display, CurrentTime );
838 dprintf_win(stddeb, "ReleaseCapture\n");
841 /**********************************************************************
842 * GetCapture (USER.236)
850 /***********************************************************************
851 * GetMouseEventProc (USER.337)
853 FARPROC GetMouseEventProc(void)
855 HMODULE hmodule = GetModuleHandle("USER");
856 return MODULE_GetEntryPoint( hmodule,
857 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
861 /***********************************************************************
862 * Mouse_Event (USER.299)
865 void Mouse_Event( struct sigcontext_struct context )
869 * BX = horizontal displacement if AX & ME_MOVE
870 * CX = vertical displacement if AX & ME_MOVE
871 * DX = button state (?)
872 * SI = mouse event flags (?)
875 int rootX, rootY, childX, childY;
878 if (AX_reg(&context) & ME_MOVE)
880 /* We have to actually move the cursor */
881 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
882 (short)BX_reg(&context), (short)CX_reg(&context) );
885 if (!XQueryPointer( display, rootWindow, &root, &child,
886 &rootX, &rootY, &childX, &childY, &state )) return;
887 if (AX_reg(&context) & ME_LDOWN)
888 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
889 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
890 if (AX_reg(&context) & ME_LUP)
891 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
892 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
893 if (AX_reg(&context) & ME_RDOWN)
894 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
895 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
896 if (AX_reg(&context) & ME_RUP)
897 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
898 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
903 /**********************************************************************
904 * EnableHardwareInput [USER.331]
906 BOOL EnableHardwareInput(BOOL bEnable)
908 BOOL bOldState = InputEnabled;
909 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
910 InputEnabled = bEnable;
911 return (bOldState && !bEnable);