2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
6 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
14 #include <X11/Xatom.h>
20 #include "clipboard.h"
23 /* #define DEBUG_EVENT */
24 /* #define DEBUG_KEY */
30 typedef char *XPointer;
34 #ifdef WHO_NEEDS_DIRTY_HACKS
36 /* Dirty hack to compile with Sun's OpenWindows */
37 typedef char *XPointer;
41 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
43 /* X context to associate a hwnd to an X window */
44 static XContext winContext = 0;
47 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
48 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
49 BYTE KeyStateTable[256];
50 BYTE AsyncKeyStateTable[256];
51 static WORD ALTKeyState;
52 static HWND captureWnd = 0;
53 static BOOL InputEnabled = TRUE;
55 /* Keyboard translation tables */
56 static int special_key[] =
58 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
59 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
60 0, 0, 0, VK_ESCAPE /* FF18 */
65 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
66 VK_NEXT, VK_END /* FF50 */
71 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
72 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
77 VK_MENU, VK_NUMLOCK, /* FF7E */
78 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
79 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
80 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
83 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
84 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
85 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
86 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
87 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
90 static function_key[] =
92 VK_F1, VK_F2, /* FFBE */
93 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
94 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
97 static modifier_key[] =
99 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
101 0, VK_MENU, VK_MENU /* FFE8 */
108 unsigned long count : 16;
109 unsigned long code : 8;
110 unsigned long extended : 1;
112 unsigned long context : 1;
113 unsigned long previous : 1;
114 unsigned long transition : 1;
119 static BOOL KeyDown = FALSE;
122 static char *event_names[] =
124 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
125 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
126 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
127 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
128 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
129 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
130 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
131 "ClientMessage", "MappingNotify"
135 static void EVENT_key( XKeyEvent *event );
136 static void EVENT_ButtonPress( XButtonEvent *event );
137 static void EVENT_ButtonRelease( XButtonEvent *event );
138 static void EVENT_MotionNotify( XMotionEvent *event );
139 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
140 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
141 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
142 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
143 static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
144 static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
147 /***********************************************************************
150 * Process an X event.
152 void EVENT_ProcessEvent( XEvent *event )
157 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
158 hwnd = (HWND) (int)ptr;
160 dprintf_event(stddeb, "Got event %s for hwnd %d\n",
161 event_names[event->type], hwnd );
167 EVENT_key( (XKeyEvent*)event );
171 EVENT_ButtonPress( (XButtonEvent*)event );
175 EVENT_ButtonRelease( (XButtonEvent*)event );
179 /* Wine between two fast machines across the overloaded campus
180 ethernet gets very boged down in MotionEvents. The following
181 simply finds the last motion event in the queue and drops
182 the rest. On a good link events are servered before they build
183 up so this doesn't take place. On a slow link this may cause
184 problems if the event order is important. I'm not yet seen
185 of any problems. Jon 7/6/96.
187 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
188 MotionNotify, event));
189 EVENT_MotionNotify( (XMotionEvent*)event );
193 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
197 EVENT_Expose( hwnd, (XExposeEvent*)event );
200 case ConfigureNotify:
201 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
204 case SelectionRequest:
205 EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
208 case SelectionNotify:
209 EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
213 EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
217 dprintf_event(stddeb, "Unprocessed event %s for hwnd %d\n",
218 event_names[event->type], hwnd );
224 /***********************************************************************
225 * EVENT_RegisterWindow
227 * Associate an X window to a HWND.
229 void EVENT_RegisterWindow( Window w, HWND hwnd )
231 if (!winContext) winContext = XUniqueContext();
232 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
236 /***********************************************************************
237 * EVENT_XStateToKeyState
239 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
240 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
242 static WORD EVENT_XStateToKeyState( int state )
246 if (state & Button1Mask) kstate |= MK_LBUTTON;
247 if (state & Button2Mask) kstate |= MK_MBUTTON;
248 if (state & Button3Mask) kstate |= MK_RBUTTON;
249 if (state & ShiftMask) kstate |= MK_SHIFT;
250 if (state & ControlMask) kstate |= MK_CONTROL;
255 /***********************************************************************
258 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
264 /* Make position relative to client area instead of window */
265 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
266 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
267 rect.right = rect.left + event->width;
268 rect.bottom = rect.top + event->height;
270 RedrawWindow( hwnd, &rect, 0,
271 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
272 (event->count ? 0 : RDW_ERASENOW) );
276 /***********************************************************************
279 * Handle a X key event
281 static void EVENT_key( XKeyEvent *event )
286 WORD xkey, vkey, key_type, key;
288 BOOL extended = FALSE;
290 int count = XLookupString(event, Str, 1, &keysym, &cs);
292 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
293 keysym, count, Str[0], Str);
295 xkey = LOWORD(keysym);
296 key_type = HIBYTE(xkey);
298 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
300 if (key_type == 0xFF) /* non-character key */
302 if (key >= 0x08 && key <= 0x1B) /* special key */
303 vkey = special_key[key - 0x08];
304 else if (key >= 0x50 && key <= 0x57) /* cursor key */
305 vkey = cursor_key[key - 0x50];
306 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
307 vkey = misc_key[key - 0x60];
308 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
310 vkey = keypad_key[key - 0x7E];
313 else if (key >= 0xBE && key <= 0xCD) /* function key */
315 vkey = function_key[key - 0xBE];
318 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
319 vkey = modifier_key[key - 0xE1];
320 else if (key == 0xFF) /* DEL key */
323 else if (key_type == 0) /* character key */
325 if (key >= 0x61 && key <= 0x7A)
326 vkey = key - 0x20; /* convert lower to uppercase */
331 if (event->type == KeyPress)
333 if (vkey == VK_MENU) ALTKeyState = TRUE;
334 if (!(KeyStateTable[vkey] & 0x0f))
335 KeyStateTable[vkey] ^= 0x80;
336 KeyStateTable[vkey] |= 0x01;
338 keylp.lp1.code = LOBYTE(event->keycode);
339 keylp.lp1.extended = (extended ? 1 : 0);
340 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
341 keylp.lp1.previous = (KeyDown ? 0 : 1);
342 keylp.lp1.transition = 0;
343 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
345 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
346 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
348 event->x_root - desktopX, event->y_root - desktopY,
352 /* The key translation ought to take place in TranslateMessage().
353 * However, there is no way of passing the required information
354 * in a Windows message, so TranslateMessage does not currently
355 * do anything and the translation is done here.
357 if (count == 1) /* key has an ASCII representation */
359 dprintf_key(stddeb,"WM_CHAR : wParam=%X\n", (WORD)Str[0] );
360 PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
365 if (vkey == VK_MENU) ALTKeyState = FALSE;
366 KeyStateTable[vkey] &= 0xf0;
368 keylp.lp1.code = LOBYTE(event->keycode);
369 keylp.lp1.extended = (extended ? 1 : 0);
370 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
371 keylp.lp1.previous = 1;
372 keylp.lp1.transition = 1;
373 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
375 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
376 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
377 WM_SYSKEYUP : WM_KEYUP),
379 event->x_root - desktopX, event->y_root - desktopY,
386 /***********************************************************************
389 static void EVENT_MotionNotify( XMotionEvent *event )
391 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
392 event->x_root - desktopX, event->y_root - desktopY,
397 /***********************************************************************
400 static void EVENT_ButtonPress( XButtonEvent *event )
402 static WORD messages[NB_BUTTONS] =
403 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
404 int buttonNum = event->button - 1;
406 if (buttonNum >= NB_BUTTONS) return;
407 MouseButtonsStates[buttonNum] = TRUE;
408 AsyncMouseButtonsStates[buttonNum] = TRUE;
409 hardware_event( messages[buttonNum],
410 EVENT_XStateToKeyState( event->state ), 0L,
411 event->x_root - desktopX, event->y_root - desktopY,
416 /***********************************************************************
417 * EVENT_ButtonRelease
419 static void EVENT_ButtonRelease( XButtonEvent *event )
421 static const WORD messages[NB_BUTTONS] =
422 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
423 int buttonNum = event->button - 1;
425 if (buttonNum >= NB_BUTTONS) return;
426 MouseButtonsStates[buttonNum] = FALSE;
427 hardware_event( messages[buttonNum],
428 EVENT_XStateToKeyState( event->state ), 0L,
429 event->x_root - desktopX, event->y_root - desktopY,
434 /**********************************************************************
437 * Note: only top-level override-redirect windows get FocusOut events.
439 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
441 if (event->detail == NotifyPointer) return;
442 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
443 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
447 /**********************************************************************
448 * EVENT_ConfigureNotify
450 * The ConfigureNotify event is only selected on the desktop window.
452 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
459 /***********************************************************************
460 * EVENT_SelectionRequest
462 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
464 XSelectionEvent result;
466 Window request=event->requestor;
468 if(event->target == XA_STRING)
472 rprop=event->property;
473 if(rprop == None)rprop=event->target;
474 if(event->selection!=XA_PRIMARY)rprop=None;
475 else if(!IsClipboardFormatAvailable(CF_TEXT))rprop=None;
477 /* Don't worry if we can't open */
478 BOOL couldOpen=OpenClipboard(hwnd);
479 hText=GetClipboardData(CF_TEXT);
480 text=GlobalLock(hText);
481 XChangeProperty(display,request,rprop,XA_STRING,
482 8,PropModeReplace,text,strlen(text));
484 /* close only if we opened before */
485 if(couldOpen)CloseClipboard();
488 if(rprop==None) dprintf_event(stddeb,"Request for %s ignored\n",
489 XGetAtomName(display,event->target));
490 result.type=SelectionNotify;
491 result.display=display;
492 result.requestor=request;
493 result.selection=event->selection;
494 result.property=rprop;
495 result.target=event->target;
496 result.time=event->time;
497 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
501 /***********************************************************************
502 * EVENT_SelectionNotify
504 static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
506 if(event->selection!=XA_PRIMARY)return;
507 if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
508 CLIPBOARD_ReadSelection(event->requestor,event->property);
512 /***********************************************************************
513 * EVENT_SelectionClear
515 static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
517 if(event->selection!=XA_PRIMARY)return;
518 CLIPBOARD_ReleaseSelection(hwnd);
521 /**********************************************************************
522 * SetCapture (USER.18)
524 HWND SetCapture( HWND hwnd )
527 HWND old_capture_wnd = captureWnd;
529 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
530 if (XGrabPointer(display, win, False,
531 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
532 GrabModeAsync, GrabModeAsync,
533 None, None, CurrentTime ) == GrabSuccess)
536 return old_capture_wnd;
542 /**********************************************************************
543 * ReleaseCapture (USER.19)
545 void ReleaseCapture()
547 if (captureWnd == 0) return;
548 XUngrabPointer( display, CurrentTime );
552 /**********************************************************************
553 * GetCapture (USER.236)
561 /**********************************************************************
562 * EnableHardwareInput [USER.331]
564 BOOL EnableHardwareInput(BOOL bEnable)
566 BOOL bOldState = InputEnabled;
567 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
568 InputEnabled = bEnable;
569 return (bOldState && !bEnable);