2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
14 #include <sys/types.h>
16 #include <X11/keysym.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
27 #include "clipboard.h"
34 #include "registers.h"
40 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
42 /* X context to associate a hwnd to an X window */
43 static XContext winContext = 0;
46 BOOL MouseButtonsStates[NB_BUTTONS];
47 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
48 BYTE KeyStateTable[256];
49 BYTE AsyncKeyStateTable[256];
52 WPARAM lastEventChar = 0; /* this will have to be changed once
53 * ToAscii starts working */
55 static HWND captureWnd = 0;
56 static BOOL InputEnabled = TRUE;
58 /* Keyboard translation tables */
59 static const int special_key[] =
61 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
62 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
63 0, 0, 0, VK_ESCAPE /* FF18 */
66 static const int cursor_key[] =
68 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
69 VK_NEXT, VK_END /* FF50 */
72 static const int misc_key[] =
74 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
78 static const int keypad_key[] =
80 VK_MENU, VK_NUMLOCK, /* FF7E */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
82 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
85 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
86 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
87 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
88 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
89 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
90 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
93 static const int function_key[] =
95 VK_F1, VK_F2, /* FFBE */
96 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
97 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
100 static const int modifier_key[] =
102 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
104 0, VK_MENU, VK_MENU /* FFE8 */
111 unsigned long count : 16;
112 unsigned long code : 8;
113 unsigned long extended : 1;
115 unsigned long reserved : 2;
116 unsigned long context : 1;
117 unsigned long previous : 1;
118 unsigned long transition : 1;
123 static BOOL KeyDown = FALSE;
125 static const char * const event_names[] =
127 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
128 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
129 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
130 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
131 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
132 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
133 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
134 "ClientMessage", "MappingNotify"
138 static void EVENT_key( XKeyEvent *event );
139 static void EVENT_ButtonPress( XButtonEvent *event );
140 static void EVENT_ButtonRelease( XButtonEvent *event );
141 static void EVENT_MotionNotify( XMotionEvent *event );
142 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
143 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
144 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
145 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
146 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
147 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
148 static void EVENT_SelectionNotify( XSelectionEvent *event);
149 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
150 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
151 static void EVENT_MapNotify( HWND hwnd, XMapEvent *event );
153 /* Usable only with OLVWM - compile option perhaps?
154 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
157 /***********************************************************************
160 * Process an X event.
162 void EVENT_ProcessEvent( XEvent *event )
166 if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
167 (char **)&pWnd ) != 0)
168 return; /* Not for a registered window */
170 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
171 event_names[event->type], pWnd->hwndSelf );
177 EVENT_key( (XKeyEvent*)event );
181 EVENT_ButtonPress( (XButtonEvent*)event );
185 EVENT_ButtonRelease( (XButtonEvent*)event );
189 /* Wine between two fast machines across the overloaded campus
190 ethernet gets very boged down in MotionEvents. The following
191 simply finds the last motion event in the queue and drops
192 the rest. On a good link events are servered before they build
193 up so this doesn't take place. On a slow link this may cause
194 problems if the event order is important. I'm not yet seen
195 of any problems. Jon 7/6/96.
197 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
198 MotionNotify, event));
199 EVENT_MotionNotify( (XMotionEvent*)event );
203 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
207 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
211 EVENT_Expose( pWnd, (XExposeEvent *)event );
215 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
218 case ConfigureNotify:
219 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
222 case SelectionRequest:
223 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
226 case SelectionNotify:
227 EVENT_SelectionNotify( (XSelectionEvent *)event );
231 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
235 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
238 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
244 /* We get all these because of StructureNotifyMask. */
246 case CirculateNotify:
254 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
258 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
259 event_names[event->type], pWnd->hwndSelf );
265 /***********************************************************************
266 * EVENT_RegisterWindow
268 * Associate an X window to a HWND.
270 void EVENT_RegisterWindow( WND *pWnd )
272 if (!winContext) winContext = XUniqueContext();
273 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
277 /***********************************************************************
280 * Wait for an X event, optionally sleeping until one arrives.
281 * Return TRUE if an event is pending, FALSE on timeout or error
282 * (for instance lost connection with the server).
284 BOOL EVENT_WaitXEvent( BOOL sleep )
287 struct timeval timeout;
289 int fd = ConnectionNumber(display);
291 if (!XPending(display))
293 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
295 FD_ZERO( &read_set );
296 FD_SET( fd, &read_set );
298 timeout.tv_usec = (maxWait % 1000) * 1000;
299 timeout.tv_sec = maxWait / 1000;
302 sigsetjmp(env_wait_x, 1);
305 if (DDE_GetRemoteMessage()) {
306 while(DDE_GetRemoteMessage())
310 stop_wait_op = STOP_WAIT_X;
311 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
312 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
316 TIMER_ExpireTimers();
319 else stop_wait_op = CONT;
320 #else /* CONFIG_IPC */
321 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
323 /* Timeout or error */
324 TIMER_ExpireTimers();
327 #endif /* CONFIG_IPC */
331 /* Process the event (and possibly others that occurred in the meantime) */
336 if (DDE_GetRemoteMessage())
338 while(DDE_GetRemoteMessage()) ;
341 #endif /* CONFIG_IPC */
343 XNextEvent( display, &event );
344 EVENT_ProcessEvent( &event );
346 while (XPending( display ));
351 /***********************************************************************
354 * Synchronize with the X server. Should not be used too often.
356 void EVENT_Synchronize()
360 XSync( display, False );
361 while (XPending( display ))
363 XNextEvent( display, &event );
364 EVENT_ProcessEvent( &event );
369 /***********************************************************************
370 * EVENT_XStateToKeyState
372 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
373 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
375 static WORD EVENT_XStateToKeyState( int state )
379 if (state & Button1Mask) kstate |= MK_LBUTTON;
380 if (state & Button2Mask) kstate |= MK_MBUTTON;
381 if (state & Button3Mask) kstate |= MK_RBUTTON;
382 if (state & ShiftMask) kstate |= MK_SHIFT;
383 if (state & ControlMask) kstate |= MK_CONTROL;
388 /***********************************************************************
391 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
395 /* Make position relative to client area instead of window */
396 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
397 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
398 rect.right = rect.left + event->width;
399 rect.bottom = rect.top + event->height;
401 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
402 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
403 (event->count ? 0 : RDW_ERASENOW) );
407 /***********************************************************************
408 * EVENT_GraphicsExpose
410 * This is needed when scrolling area is partially obscured
411 * by non-Wine X window.
413 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
417 /* Make position relative to client area instead of window */
418 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
419 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
420 rect.right = rect.left + event->width;
421 rect.bottom = rect.top + event->height;
423 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
424 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
425 (event->count ? 0 : RDW_ERASENOW) );
429 /***********************************************************************
432 * Handle a X key event
434 static void EVENT_key( XKeyEvent *event )
440 WORD xkey, key_type, key;
442 BOOL extended = FALSE;
444 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
446 Str[ascii_chars] = '\0';
447 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
448 keysym, ascii_chars, Str[0], Str);
450 /* Ctrl-Alt-Return enters the debugger */
451 if ((keysym == XK_Return) && (event->type == KeyPress) &&
452 (event->state & ControlMask) && (event->state & Mod1Mask))
453 DEBUG_EnterDebugger();
455 xkey = LOWORD(keysym);
456 key_type = HIBYTE(xkey);
458 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
460 if (key_type == 0xFF) /* non-character key */
462 if (key >= 0x08 && key <= 0x1B) /* special key */
463 vkey = special_key[key - 0x08];
464 else if (key >= 0x50 && key <= 0x57) /* cursor key */
465 vkey = cursor_key[key - 0x50];
466 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
467 vkey = misc_key[key - 0x60];
468 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
470 vkey = keypad_key[key - 0x7E];
473 else if (key >= 0xBE && key <= 0xCD) /* function key */
475 vkey = function_key[key - 0xBE];
478 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
479 vkey = modifier_key[key - 0xE1];
480 else if (key == 0xFF) /* DEL key */
483 else if (key_type == 0) /* character key */
486 vkey = toupper(key); /* convert lc to uc */
487 else if ( isspace(key) )
488 vkey = key; /* XXX approximately */
490 switch (key) /* the rest... */
492 #define vkcase(k,val) case k: vkey = val; break;
493 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
495 /* I wish I had a bit-paired keyboard! */
496 vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
497 vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
498 vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
501 vkcase2('`','~',0xc0);
502 vkcase2('-','_',0xbd);
503 vkcase2('=','+',0xbb);
504 vkcase2('[','{',0xdb);
505 vkcase2(']','}',0xdd);
506 vkcase2(';',':',0xba);
507 vkcase2('\'','\"',0xde);
508 vkcase2(',','<',0xbc);
509 vkcase2('.','>',0xbe);
510 vkcase2('/','?',0xbf);
511 vkcase2('\\','|',0xdc);
515 fprintf( stderr, "Unknown key! Please report!\n" );
516 vkey = 0; /* whatever */
520 if (event->type == KeyPress)
522 if (!(KeyStateTable[vkey] & 0x80))
523 KeyStateTable[vkey] ^= 0x01;
524 KeyStateTable[vkey] |= 0x80;
526 keylp.lp1.code = LOBYTE(event->keycode) - 8;
527 keylp.lp1.extended = (extended ? 1 : 0);
528 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
529 keylp.lp1.context = ( (event->state & Mod1Mask) ||
530 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
531 keylp.lp1.previous = (KeyDown ? 0 : 1);
532 keylp.lp1.transition = 0;
533 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
535 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
536 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
538 event->x_root - desktopX, event->y_root - desktopY,
542 /* Currently we use reserved field in the scan-code byte to
543 * make it possible for TranslateMessage to recognize character keys
544 * and get them from lastEventChar global variable.
546 * ToAscii should handle it.
549 if( ascii_chars ) lastEventChar = Str[0];
553 UINT sysKey = KeyStateTable[VK_MENU];
555 KeyStateTable[vkey] &= ~0x80;
557 keylp.lp1.code = LOBYTE(event->keycode) - 8;
558 keylp.lp1.extended = (extended ? 1 : 0);
559 keylp.lp1.reserved = 0;
560 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
561 keylp.lp1.previous = 1;
562 keylp.lp1.transition = 1;
563 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
565 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
566 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
568 event->x_root - desktopX, event->y_root - desktopY,
575 /***********************************************************************
578 static void EVENT_MotionNotify( XMotionEvent *event )
580 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
581 event->x_root - desktopX, event->y_root - desktopY,
586 /***********************************************************************
587 * EVENT_DummyMotionNotify
589 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
591 void EVENT_DummyMotionNotify(void)
594 int rootX, rootY, childX, childY;
597 if (XQueryPointer( display, rootWindow, &root, &child,
598 &rootX, &rootY, &childX, &childY, &state ))
600 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
601 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
606 /***********************************************************************
609 static void EVENT_ButtonPress( XButtonEvent *event )
611 static WORD messages[NB_BUTTONS] =
612 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
613 int buttonNum = event->button - 1;
615 if (buttonNum >= NB_BUTTONS) return;
616 MouseButtonsStates[buttonNum] = 0x8000;
617 AsyncMouseButtonsStates[buttonNum] = 0x8000;
618 hardware_event( messages[buttonNum],
619 EVENT_XStateToKeyState( event->state ), 0L,
620 event->x_root - desktopX, event->y_root - desktopY,
625 /***********************************************************************
626 * EVENT_ButtonRelease
628 static void EVENT_ButtonRelease( XButtonEvent *event )
630 static const WORD messages[NB_BUTTONS] =
631 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
632 int buttonNum = event->button - 1;
634 if (buttonNum >= NB_BUTTONS) return;
635 MouseButtonsStates[buttonNum] = FALSE;
636 hardware_event( messages[buttonNum],
637 EVENT_XStateToKeyState( event->state ), 0L,
638 event->x_root - desktopX, event->y_root - desktopY,
643 /**********************************************************************
646 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
648 if (event->detail == NotifyPointer) return;
649 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
650 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
654 /**********************************************************************
657 * Note: only top-level override-redirect windows get FocusOut events.
659 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
661 if (event->detail == NotifyPointer) return;
662 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
663 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
667 /**********************************************************************
668 * EVENT_ConfigureNotify
670 * The ConfigureNotify event is only selected on the desktop window
671 * and on top-level windows when the -managed flag is used.
673 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
675 /* FIXME: with -desktop xxx we get this event _before_ desktop
676 * window structure is created. WIN_GetDesktop() check is a hack.
679 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
686 /* Managed window; most of this code is shamelessly
687 * stolen from SetWindowPos - FIXME: outdated
692 RECT16 newWindowRect, newClientRect;
693 HRGN hrgnOldPos, hrgnNewPos;
695 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
697 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
701 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
703 /* Artificial messages - what is this for? */
704 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
705 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
707 /* Fill WINDOWPOS struct */
708 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
710 winpos->x = event->x;
711 winpos->y = event->y;
712 winpos->cx = event->width;
713 winpos->cy = event->height;
715 /* Check for unchanged attributes */
716 if(winpos->x == wndPtr->rectWindow.left &&
717 winpos->y == wndPtr->rectWindow.top)
718 winpos->flags |= SWP_NOMOVE;
719 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
720 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
721 winpos->flags |= SWP_NOSIZE;
723 /* Send WM_WINDOWPOSCHANGING */
724 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
726 /* Calculate new position and size */
727 newWindowRect.left = event->x;
728 newWindowRect.right = event->x + event->width;
729 newWindowRect.top = event->y;
730 newWindowRect.bottom = event->y + event->height;
732 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
733 &wndPtr->rectWindow, &wndPtr->rectClient,
734 SEGPTR_GET(winpos), &newClientRect );
736 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
737 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
738 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
740 /* Set new size and position */
741 wndPtr->rectWindow = newWindowRect;
742 wndPtr->rectClient = newClientRect;
743 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
746 /* full window drag leaves unrepainted garbage without this */
747 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
748 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
749 DeleteObject(hrgnOldPos);
750 DeleteObject(hrgnNewPos);
755 /***********************************************************************
756 * EVENT_SelectionRequest
758 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
760 XSelectionEvent result;
762 Window request = event->requestor;
764 if(event->target == XA_STRING)
769 rprop = event->property;
771 if(rprop == None) rprop = event->target;
773 if(event->selection!=XA_PRIMARY) rprop = None;
774 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
776 /* Don't worry if we can't open */
777 BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
778 hText=GetClipboardData(CF_TEXT);
779 text=GlobalLock16(hText);
780 XChangeProperty(display,request,rprop,XA_STRING,
781 8,PropModeReplace,text,strlen(text));
782 GlobalUnlock16(hText);
783 /* close only if we opened before */
784 if(couldOpen)CloseClipboard();
789 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
791 result.type=SelectionNotify;
792 result.display=display;
793 result.requestor=request;
794 result.selection=event->selection;
795 result.property=rprop;
796 result.target=event->target;
797 result.time=event->time;
798 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
802 /***********************************************************************
803 * EVENT_SelectionNotify
805 static void EVENT_SelectionNotify( XSelectionEvent *event )
807 if (event->selection != XA_PRIMARY) return;
808 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
809 CLIPBOARD_ReadSelection( event->requestor, event->property );
813 /***********************************************************************
814 * EVENT_SelectionClear
816 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
818 if (event->selection != XA_PRIMARY) return;
819 CLIPBOARD_ReleaseSelection( pWnd->hwndSelf );
823 /**********************************************************************
824 * EVENT_ClientMessage
826 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
828 static Atom wmProtocols = None;
829 static Atom wmDeleteWindow = None;
831 if (wmProtocols == None)
832 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
833 if (wmDeleteWindow == None)
834 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
836 if ((event->format != 32) || (event->message_type != wmProtocols) ||
837 (((Atom) event->data.l[0]) != wmDeleteWindow))
839 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
842 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
845 /**********************************************************************
848 * Install colormap when Wine window is focused in
849 * self-managed mode with private colormap
852 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
854 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
855 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus() )
856 XInstallColormap( display, COLOR_GetColormap() );
860 /**********************************************************************
863 void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
865 HWND hwndFocus = GetFocus();
867 if (hwndFocus && IsChild( hWnd, hwndFocus ))
868 FOCUS_SetXFocus(hwndFocus);
873 /**********************************************************************
874 * SetCapture (USER.18)
876 HWND SetCapture( HWND hwnd )
879 HWND old_capture_wnd = captureWnd;
884 return old_capture_wnd;
886 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
887 if (XGrabPointer(display, win, False,
888 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
889 GrabModeAsync, GrabModeAsync,
890 None, None, CurrentTime ) == GrabSuccess)
892 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
894 return old_capture_wnd;
900 /**********************************************************************
901 * ReleaseCapture (USER.19)
903 void ReleaseCapture()
905 if (captureWnd == 0) return;
906 XUngrabPointer( display, CurrentTime );
908 dprintf_win(stddeb, "ReleaseCapture\n");
911 /**********************************************************************
912 * GetCapture (USER.236)
920 /***********************************************************************
921 * GetMouseEventProc (USER.337)
923 FARPROC16 GetMouseEventProc(void)
925 HMODULE16 hmodule = GetModuleHandle("USER");
926 return MODULE_GetEntryPoint( hmodule,
927 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
931 /***********************************************************************
932 * Mouse_Event (USER.299)
935 void Mouse_Event( SIGCONTEXT *context )
939 * BX = horizontal displacement if AX & ME_MOVE
940 * CX = vertical displacement if AX & ME_MOVE
941 * DX = button state (?)
942 * SI = mouse event flags (?)
945 int rootX, rootY, childX, childY;
948 if (AX_reg(context) & ME_MOVE)
950 /* We have to actually move the cursor */
951 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
952 (short)BX_reg(context), (short)CX_reg(context) );
955 if (!XQueryPointer( display, rootWindow, &root, &child,
956 &rootX, &rootY, &childX, &childY, &state )) return;
957 if (AX_reg(context) & ME_LDOWN)
958 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
959 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
960 if (AX_reg(context) & ME_LUP)
961 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
962 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
963 if (AX_reg(context) & ME_RDOWN)
964 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
965 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
966 if (AX_reg(context) & ME_RUP)
967 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
968 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
973 /**********************************************************************
974 * EnableHardwareInput [USER.331]
976 BOOL EnableHardwareInput(BOOL bEnable)
978 BOOL bOldState = InputEnabled;
979 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
980 InputEnabled = bEnable;
981 return (bOldState && !bEnable);