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"
33 #include "registers.h"
39 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
41 /* X context to associate a hwnd to an X window */
42 static XContext winContext = 0;
45 BOOL MouseButtonsStates[NB_BUTTONS];
46 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
47 BYTE KeyStateTable[256];
48 BYTE AsyncKeyStateTable[256];
51 WPARAM lastEventChar = 0; /* this will have to be changed once
52 * ToAscii starts working */
54 static HWND captureWnd = 0;
55 static BOOL InputEnabled = TRUE;
57 /* Keyboard translation tables */
58 static const int special_key[] =
60 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
61 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
62 0, 0, 0, VK_ESCAPE /* FF18 */
65 static const int cursor_key[] =
67 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
68 VK_NEXT, VK_END /* FF50 */
71 static const int misc_key[] =
73 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
74 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
77 static const int keypad_key[] =
79 VK_MENU, VK_NUMLOCK, /* FF7E */
80 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
81 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
85 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
86 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
87 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
88 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
89 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
92 static const int function_key[] =
94 VK_F1, VK_F2, /* FFBE */
95 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
96 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
99 static const int modifier_key[] =
101 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
103 0, VK_MENU, VK_MENU /* FFE8 */
110 unsigned long count : 16;
111 unsigned long code : 8;
112 unsigned long extended : 1;
114 unsigned long reserved : 2;
115 unsigned long context : 1;
116 unsigned long previous : 1;
117 unsigned long transition : 1;
122 static BOOL KeyDown = FALSE;
124 static const char * const event_names[] =
126 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
127 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
128 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
129 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
130 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
131 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
132 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
133 "ClientMessage", "MappingNotify"
137 static void EVENT_key( XKeyEvent *event );
138 static void EVENT_ButtonPress( XButtonEvent *event );
139 static void EVENT_ButtonRelease( XButtonEvent *event );
140 static void EVENT_MotionNotify( XMotionEvent *event );
141 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
142 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
143 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
144 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
145 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
146 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
147 static void EVENT_SelectionNotify( XSelectionEvent *event);
148 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
149 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
152 /***********************************************************************
155 * Process an X event.
157 void EVENT_ProcessEvent( XEvent *event )
161 if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
162 (char **)&pWnd ) != 0)
163 return; /* Not for a registered window */
165 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
166 event_names[event->type], pWnd->hwndSelf );
172 EVENT_key( (XKeyEvent*)event );
176 EVENT_ButtonPress( (XButtonEvent*)event );
180 EVENT_ButtonRelease( (XButtonEvent*)event );
184 /* Wine between two fast machines across the overloaded campus
185 ethernet gets very boged down in MotionEvents. The following
186 simply finds the last motion event in the queue and drops
187 the rest. On a good link events are servered before they build
188 up so this doesn't take place. On a slow link this may cause
189 problems if the event order is important. I'm not yet seen
190 of any problems. Jon 7/6/96.
192 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
193 MotionNotify, event));
194 EVENT_MotionNotify( (XMotionEvent*)event );
198 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
202 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
206 EVENT_Expose( pWnd, (XExposeEvent *)event );
210 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
213 case ConfigureNotify:
214 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
217 case SelectionRequest:
218 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
221 case SelectionNotify:
222 EVENT_SelectionNotify( (XSelectionEvent *)event );
226 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
230 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
237 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
238 event_names[event->type], pWnd->hwndSelf );
244 /***********************************************************************
245 * EVENT_RegisterWindow
247 * Associate an X window to a HWND.
249 void EVENT_RegisterWindow( WND *pWnd )
251 if (!winContext) winContext = XUniqueContext();
252 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
256 /***********************************************************************
259 * Wait for an X event, optionally sleeping until one arrives.
260 * Return TRUE if an event is pending, FALSE on timeout or error
261 * (for instance lost connection with the server).
263 BOOL EVENT_WaitXEvent( BOOL sleep )
266 struct timeval timeout;
268 int fd = ConnectionNumber(display);
270 if (!XPending(display))
272 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
274 FD_ZERO( &read_set );
275 FD_SET( fd, &read_set );
277 timeout.tv_usec = (maxWait % 1000) * 1000;
278 timeout.tv_sec = maxWait / 1000;
281 sigsetjmp(env_wait_x, 1);
284 if (DDE_GetRemoteMessage()) {
285 while(DDE_GetRemoteMessage())
289 stop_wait_op = STOP_WAIT_X;
290 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
291 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
295 TIMER_ExpireTimers();
298 else stop_wait_op = CONT;
299 #else /* CONFIG_IPC */
300 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
302 /* Timeout or error */
303 TIMER_ExpireTimers();
306 #endif /* CONFIG_IPC */
310 /* Process the event (and possibly others that occurred in the meantime) */
315 if (DDE_GetRemoteMessage())
317 while(DDE_GetRemoteMessage()) ;
320 #endif /* CONFIG_IPC */
322 XNextEvent( display, &event );
323 EVENT_ProcessEvent( &event );
325 while (XPending( display ));
330 /***********************************************************************
333 * Synchronize with the X server. Should not be used too often.
335 void EVENT_Synchronize()
339 XSync( display, False );
340 while (XPending( display ))
342 XNextEvent( display, &event );
343 EVENT_ProcessEvent( &event );
348 /***********************************************************************
349 * EVENT_XStateToKeyState
351 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
352 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
354 static WORD EVENT_XStateToKeyState( int state )
358 if (state & Button1Mask) kstate |= MK_LBUTTON;
359 if (state & Button2Mask) kstate |= MK_MBUTTON;
360 if (state & Button3Mask) kstate |= MK_RBUTTON;
361 if (state & ShiftMask) kstate |= MK_SHIFT;
362 if (state & ControlMask) kstate |= MK_CONTROL;
367 /***********************************************************************
370 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
374 /* Make position relative to client area instead of window */
375 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
376 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
377 rect.right = rect.left + event->width;
378 rect.bottom = rect.top + event->height;
380 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
381 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
382 (event->count ? 0 : RDW_ERASENOW) );
386 /***********************************************************************
387 * EVENT_GraphicsExpose
389 * This is needed when scrolling area is partially obscured
390 * by non-Wine X window.
392 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
396 /* Make position relative to client area instead of window */
397 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
398 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
399 rect.right = rect.left + event->width;
400 rect.bottom = rect.top + event->height;
402 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
403 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
404 (event->count ? 0 : RDW_ERASENOW) );
408 /***********************************************************************
411 * Handle a X key event
413 static void EVENT_key( XKeyEvent *event )
419 WORD xkey, key_type, key;
421 BOOL extended = FALSE;
423 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
425 Str[ascii_chars] = '\0';
426 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
427 keysym, ascii_chars, Str[0], Str);
429 /* Ctrl-Alt-Return enters the debugger */
430 if ((keysym == XK_Return) && (event->type == KeyPress) &&
431 (event->state & ControlMask) && (event->state & Mod1Mask))
432 DEBUG_EnterDebugger();
434 xkey = LOWORD(keysym);
435 key_type = HIBYTE(xkey);
437 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
439 if (key_type == 0xFF) /* non-character key */
441 if (key >= 0x08 && key <= 0x1B) /* special key */
442 vkey = special_key[key - 0x08];
443 else if (key >= 0x50 && key <= 0x57) /* cursor key */
444 vkey = cursor_key[key - 0x50];
445 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
446 vkey = misc_key[key - 0x60];
447 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
449 vkey = keypad_key[key - 0x7E];
452 else if (key >= 0xBE && key <= 0xCD) /* function key */
454 vkey = function_key[key - 0xBE];
457 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
458 vkey = modifier_key[key - 0xE1];
459 else if (key == 0xFF) /* DEL key */
462 else if (key_type == 0) /* character key */
465 vkey = toupper(key); /* convert lower to uppercase */
470 if (event->type == KeyPress)
472 if (!(KeyStateTable[vkey] & 0x80))
473 KeyStateTable[vkey] ^= 0x01;
474 KeyStateTable[vkey] |= 0x80;
476 keylp.lp1.code = LOBYTE(event->keycode) - 8;
477 keylp.lp1.extended = (extended ? 1 : 0);
478 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
479 keylp.lp1.context = ( (event->state & Mod1Mask) ||
480 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
481 keylp.lp1.previous = (KeyDown ? 0 : 1);
482 keylp.lp1.transition = 0;
483 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
485 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
486 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
488 event->x_root - desktopX, event->y_root - desktopY,
492 /* Currently we use reserved field in the scan-code byte to
493 * make it possible for TranslateMessage to recognize character keys
494 * and get them from lastEventChar global variable.
496 * ToAscii should handle it.
499 if( ascii_chars ) lastEventChar = Str[0];
503 UINT sysKey = KeyStateTable[VK_MENU];
505 KeyStateTable[vkey] &= ~0x80;
507 keylp.lp1.code = LOBYTE(event->keycode) - 8;
508 keylp.lp1.extended = (extended ? 1 : 0);
509 keylp.lp1.reserved = 0;
510 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
511 keylp.lp1.previous = 1;
512 keylp.lp1.transition = 1;
513 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
515 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
516 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
518 event->x_root - desktopX, event->y_root - desktopY,
525 /***********************************************************************
528 static void EVENT_MotionNotify( XMotionEvent *event )
530 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
531 event->x_root - desktopX, event->y_root - desktopY,
536 /***********************************************************************
537 * EVENT_DummyMotionNotify
539 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
541 void EVENT_DummyMotionNotify(void)
544 int rootX, rootY, childX, childY;
547 if (XQueryPointer( display, rootWindow, &root, &child,
548 &rootX, &rootY, &childX, &childY, &state ))
550 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
551 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
556 /***********************************************************************
559 static void EVENT_ButtonPress( XButtonEvent *event )
561 static WORD messages[NB_BUTTONS] =
562 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
563 int buttonNum = event->button - 1;
565 if (buttonNum >= NB_BUTTONS) return;
566 MouseButtonsStates[buttonNum] = 0x8000;
567 AsyncMouseButtonsStates[buttonNum] = 0x8000;
568 hardware_event( messages[buttonNum],
569 EVENT_XStateToKeyState( event->state ), 0L,
570 event->x_root - desktopX, event->y_root - desktopY,
575 /***********************************************************************
576 * EVENT_ButtonRelease
578 static void EVENT_ButtonRelease( XButtonEvent *event )
580 static const WORD messages[NB_BUTTONS] =
581 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
582 int buttonNum = event->button - 1;
584 if (buttonNum >= NB_BUTTONS) return;
585 MouseButtonsStates[buttonNum] = FALSE;
586 hardware_event( messages[buttonNum],
587 EVENT_XStateToKeyState( event->state ), 0L,
588 event->x_root - desktopX, event->y_root - desktopY,
593 /**********************************************************************
596 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
598 if (event->detail == NotifyPointer) return;
599 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
600 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
604 /**********************************************************************
607 * Note: only top-level override-redirect windows get FocusOut events.
609 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
611 if (event->detail == NotifyPointer) return;
612 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
613 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
617 /**********************************************************************
618 * EVENT_ConfigureNotify
620 * The ConfigureNotify event is only selected on the desktop window
621 * and on top-level windows when the -managed flag is used.
623 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
625 /* FIXME: with -desktop xxx we get this event _before_ desktop
626 * window structure is created. WIN_GetDesktop() check is a hack.
629 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
636 /* Managed window; most of this code is shamelessly
637 * stolen from SetWindowPos - FIXME: outdated
642 RECT16 newWindowRect, newClientRect;
643 HRGN hrgnOldPos, hrgnNewPos;
645 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
647 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
651 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
653 /* Artificial messages - what is this for? */
654 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
655 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
657 /* Fill WINDOWPOS struct */
658 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
660 winpos->x = event->x;
661 winpos->y = event->y;
662 winpos->cx = event->width;
663 winpos->cy = event->height;
665 /* Check for unchanged attributes */
666 if(winpos->x == wndPtr->rectWindow.left &&
667 winpos->y == wndPtr->rectWindow.top)
668 winpos->flags |= SWP_NOMOVE;
669 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
670 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
671 winpos->flags |= SWP_NOSIZE;
673 /* Send WM_WINDOWPOSCHANGING */
674 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
676 /* Calculate new position and size */
677 newWindowRect.left = event->x;
678 newWindowRect.right = event->x + event->width;
679 newWindowRect.top = event->y;
680 newWindowRect.bottom = event->y + event->height;
682 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
683 &wndPtr->rectWindow, &wndPtr->rectClient,
684 SEGPTR_GET(winpos), &newClientRect );
686 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
687 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
688 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
690 /* Set new size and position */
691 wndPtr->rectWindow = newWindowRect;
692 wndPtr->rectClient = newClientRect;
693 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
696 /* full window drag leaves unrepainted garbage without this */
697 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
698 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
699 DeleteObject(hrgnOldPos);
700 DeleteObject(hrgnNewPos);
705 /***********************************************************************
706 * EVENT_SelectionRequest
708 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
710 XSelectionEvent result;
712 Window request = event->requestor;
714 if(event->target == XA_STRING)
719 rprop = event->property;
721 if(rprop == None) rprop = event->target;
723 if(event->selection!=XA_PRIMARY) rprop = None;
724 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
726 /* Don't worry if we can't open */
727 BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
728 hText=GetClipboardData(CF_TEXT);
729 text=GlobalLock16(hText);
730 XChangeProperty(display,request,rprop,XA_STRING,
731 8,PropModeReplace,text,strlen(text));
732 GlobalUnlock16(hText);
733 /* close only if we opened before */
734 if(couldOpen)CloseClipboard();
739 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
741 result.type=SelectionNotify;
742 result.display=display;
743 result.requestor=request;
744 result.selection=event->selection;
745 result.property=rprop;
746 result.target=event->target;
747 result.time=event->time;
748 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
752 /***********************************************************************
753 * EVENT_SelectionNotify
755 static void EVENT_SelectionNotify( XSelectionEvent *event )
757 if (event->selection != XA_PRIMARY) return;
758 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
759 CLIPBOARD_ReadSelection( event->requestor, event->property );
763 /***********************************************************************
764 * EVENT_SelectionClear
766 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
768 if (event->selection != XA_PRIMARY) return;
769 CLIPBOARD_ReleaseSelection( pWnd->hwndSelf );
773 /**********************************************************************
774 * EVENT_ClientMessage
776 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
778 static Atom wmProtocols = None;
779 static Atom wmDeleteWindow = None;
781 if (wmProtocols == None)
782 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
783 if (wmDeleteWindow == None)
784 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
786 if ((event->format != 32) || (event->message_type != wmProtocols) ||
787 (((Atom) event->data.l[0]) != wmDeleteWindow))
789 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
792 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
796 /**********************************************************************
797 * SetCapture (USER.18)
799 HWND SetCapture( HWND hwnd )
802 HWND old_capture_wnd = captureWnd;
807 return old_capture_wnd;
809 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
810 if (XGrabPointer(display, win, False,
811 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
812 GrabModeAsync, GrabModeAsync,
813 None, None, CurrentTime ) == GrabSuccess)
815 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
817 return old_capture_wnd;
823 /**********************************************************************
824 * ReleaseCapture (USER.19)
826 void ReleaseCapture()
828 if (captureWnd == 0) return;
829 XUngrabPointer( display, CurrentTime );
831 dprintf_win(stddeb, "ReleaseCapture\n");
834 /**********************************************************************
835 * GetCapture (USER.236)
843 /***********************************************************************
844 * GetMouseEventProc (USER.337)
846 FARPROC GetMouseEventProc(void)
848 HMODULE hmodule = GetModuleHandle("USER");
849 return MODULE_GetEntryPoint( hmodule,
850 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
854 /***********************************************************************
855 * Mouse_Event (USER.299)
858 void Mouse_Event( struct sigcontext_struct context )
862 * BX = horizontal displacement if AX & ME_MOVE
863 * CX = vertical displacement if AX & ME_MOVE
864 * DX = button state (?)
865 * SI = mouse event flags (?)
868 int rootX, rootY, childX, childY;
871 if (AX_reg(&context) & ME_MOVE)
873 /* We have to actually move the cursor */
874 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
875 (short)BX_reg(&context), (short)CX_reg(&context) );
878 if (!XQueryPointer( display, rootWindow, &root, &child,
879 &rootX, &rootY, &childX, &childY, &state )) return;
880 if (AX_reg(&context) & ME_LDOWN)
881 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
882 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
883 if (AX_reg(&context) & ME_LUP)
884 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
885 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
886 if (AX_reg(&context) & ME_RDOWN)
887 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
888 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
889 if (AX_reg(&context) & ME_RUP)
890 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
891 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
896 /**********************************************************************
897 * EnableHardwareInput [USER.331]
899 BOOL EnableHardwareInput(BOOL bEnable)
901 BOOL bOldState = InputEnabled;
902 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
903 InputEnabled = bEnable;
904 return (bOldState && !bEnable);