2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
22 typedef char *XPointer;
27 /* Dirty hack to compile with Sun's OpenWindows */
28 typedef char *XPointer;
31 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
33 extern int desktopX, desktopY; /* misc/main.c */
35 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
37 /* X context to associate a hwnd to an X window */
38 static XContext winContext = 0;
41 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
42 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
43 BYTE KeyStateTable[256];
44 BYTE AsyncKeyStateTable[256];
45 static WORD ALTKeyState;
46 static HWND captureWnd = 0;
47 static BOOL InputEnabled = TRUE;
48 Window winHasCursor = 0;
50 /* Keyboard translation tables */
51 static int special_key[] =
53 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
54 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
55 0, 0, 0, VK_ESCAPE /* FF18 */
60 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
61 VK_NEXT, VK_END /* FF50 */
66 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
67 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
72 VK_MENU, VK_NUMLOCK, /* FF7E */
73 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
74 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
75 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
76 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
77 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
78 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
79 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
80 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
81 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
82 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
85 static function_key[] =
87 VK_F1, VK_F2, /* FFBE */
88 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
89 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
92 static modifier_key[] =
94 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
96 0, VK_MENU, VK_MENU /* FFE8 */
103 unsigned long count : 16;
104 unsigned long code : 8;
105 unsigned long extended : 1;
107 unsigned long context : 1;
108 unsigned long previous : 1;
109 unsigned long transition : 1;
114 static BOOL KeyDown = FALSE;
118 static char *event_names[] =
120 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
121 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
122 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
123 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
124 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
125 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
126 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
127 "ClientMessage", "MappingNotify"
132 static void EVENT_key( HWND hwnd, XKeyEvent *event );
133 static void EVENT_ButtonPress( XButtonEvent *event );
134 static void EVENT_ButtonRelease( XButtonEvent *event );
135 static void EVENT_MotionNotify( XMotionEvent *event );
136 static void EVENT_EnterNotify( XCrossingEvent *event );
137 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
138 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
139 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
142 /***********************************************************************
145 * Process an X event.
147 void EVENT_ProcessEvent( XEvent *event )
152 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
153 hwnd = (HWND) (int)ptr;
156 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
163 EVENT_key( hwnd, (XKeyEvent*)event );
167 EVENT_ButtonPress( (XButtonEvent*)event );
171 EVENT_ButtonRelease( (XButtonEvent*)event );
175 /* Wine between two fast machines across the overloaded campus
176 ethernet gets very boged down in MotionEvents. The following
177 simply finds the last motion event in the queue and drops
178 the rest. On a good link events are servered before they build
179 up so this doesn't take place. On a slow link this may cause
180 problems if the event order is important. I'm not yet seen
181 of any problems. Jon 7/6/96.
183 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
184 MotionNotify, event));
185 EVENT_MotionNotify( (XMotionEvent*)event );
189 EVENT_EnterNotify( (XCrossingEvent*)event );
193 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
197 EVENT_Expose( hwnd, (XExposeEvent*)event );
200 case ConfigureNotify:
201 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
206 printf( "Unprocessed event %s for hwnd %d\n",
207 event_names[event->type], hwnd );
214 /***********************************************************************
215 * EVENT_RegisterWindow
217 * Associate an X window to a HWND.
219 void EVENT_RegisterWindow( Window w, HWND hwnd )
221 if (!winContext) winContext = XUniqueContext();
222 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
226 /***********************************************************************
227 * EVENT_XStateToKeyState
229 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
230 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
232 static WORD EVENT_XStateToKeyState( int state )
236 if (state & Button1Mask) kstate |= MK_LBUTTON;
237 if (state & Button2Mask) kstate |= MK_MBUTTON;
238 if (state & Button3Mask) kstate |= MK_RBUTTON;
239 if (state & ShiftMask) kstate |= MK_SHIFT;
240 if (state & ControlMask) kstate |= MK_CONTROL;
245 /***********************************************************************
248 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
252 WND * wndPtr = WIN_FindWndPtr( hwnd );
255 if (IsIconic(hwnd) && wndPtr->hIcon)
257 SendMessage(hwnd, WM_PAINTICON, 0, 0);
262 /* Make position relative to client area instead of window */
263 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
264 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
265 rect.right = rect.left + event->width;
266 rect.bottom = rect.top + event->height;
267 winHasCursor = event->window;
269 flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
270 /* Erase desktop background synchronously */
271 if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
272 RedrawWindow( hwnd, &rect, 0, flags );
276 /***********************************************************************
279 * Handle a X key event
281 static void EVENT_key( HWND hwnd, XKeyEvent *event )
286 WORD xkey, vkey, key_type, key;
288 BOOL extended = FALSE;
290 int count = XLookupString(event, Str, 1, &keysym, &cs);
293 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
294 keysym, count, Str[0], Str);
297 xkey = LOWORD(keysym);
298 key_type = HIBYTE(xkey);
301 printf(" key_type=%X, key=%X\n", key_type, key);
304 if (key_type == 0xFF) /* non-character key */
306 if (key >= 0x08 && key <= 0x1B) /* special key */
307 vkey = special_key[key - 0x08];
308 else if (key >= 0x50 && key <= 0x57) /* cursor key */
309 vkey = cursor_key[key - 0x50];
310 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
311 vkey = misc_key[key - 0x60];
312 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
314 vkey = keypad_key[key - 0x7E];
317 else if (key >= 0xBE && key <= 0xCD) /* function key */
319 vkey = function_key[key - 0xBE];
322 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
323 vkey = modifier_key[key - 0xE1];
324 else if (key == 0xFF) /* DEL key */
327 else if (key_type == 0) /* character key */
329 if (key >= 0x61 && key <= 0x7A)
330 vkey = key - 0x20; /* convert lower to uppercase */
335 if (event->type == KeyPress)
337 if (vkey == VK_MENU) ALTKeyState = TRUE;
338 if (!(KeyStateTable[vkey] & 0x0f))
339 KeyStateTable[vkey] ^= 0x80;
340 KeyStateTable[vkey] |= 0x01;
342 keylp.lp1.code = LOBYTE(event->keycode);
343 keylp.lp1.extended = (extended ? 1 : 0);
344 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
345 keylp.lp1.previous = (KeyDown ? 0 : 1);
346 keylp.lp1.transition = 0;
348 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
349 printf(" KeyState=%X\n", KeyStateTable[vkey]);
351 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
353 event->x_root - desktopX, event->y_root - desktopY,
357 /* The key translation ought to take place in TranslateMessage().
358 * However, there is no way of passing the required information
359 * in a Windows message, so TranslateMessage does not currently
360 * do anything and the translation is done here.
362 if (count == 1) /* key has an ASCII representation */
365 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
367 PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
372 if (vkey == VK_MENU) ALTKeyState = FALSE;
373 KeyStateTable[vkey] &= 0xf0;
375 keylp.lp1.code = LOBYTE(event->keycode);
376 keylp.lp1.extended = (extended ? 1 : 0);
377 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
378 keylp.lp1.previous = 1;
379 keylp.lp1.transition = 1;
381 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
382 printf(" KeyState=%X\n", KeyStateTable[vkey]);
384 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
385 WM_SYSKEYUP : WM_KEYUP),
387 event->x_root - desktopX, event->y_root - desktopY,
394 /***********************************************************************
397 static void EVENT_MotionNotify( XMotionEvent *event )
399 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
400 event->x_root - desktopX, event->y_root - desktopY,
405 /***********************************************************************
408 static void EVENT_ButtonPress( XButtonEvent *event )
410 static WORD messages[NB_BUTTONS] =
411 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
412 int buttonNum = event->button - 1;
414 if (buttonNum >= NB_BUTTONS) return;
415 MouseButtonsStates[buttonNum] = TRUE;
416 AsyncMouseButtonsStates[buttonNum] = TRUE;
417 winHasCursor = event->window;
418 hardware_event( messages[buttonNum],
419 EVENT_XStateToKeyState( event->state ), 0L,
420 event->x_root - desktopX, event->y_root - desktopY,
425 /***********************************************************************
426 * EVENT_ButtonRelease
428 static void EVENT_ButtonRelease( XButtonEvent *event )
430 static const WORD messages[NB_BUTTONS] =
431 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
432 int buttonNum = event->button - 1;
434 if (buttonNum >= NB_BUTTONS) return;
435 MouseButtonsStates[buttonNum] = FALSE;
436 winHasCursor = event->window;
437 hardware_event( messages[buttonNum],
438 EVENT_XStateToKeyState( event->state ), 0L,
439 event->x_root - desktopX, event->y_root - desktopY,
444 /**********************************************************************
447 * Note: only top-level override-redirect windows get FocusOut events.
449 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
451 if (event->detail == NotifyPointer) return;
452 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
453 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
457 /**********************************************************************
460 static void EVENT_EnterNotify( XCrossingEvent *event )
462 if (captureWnd != 0) return;
463 winHasCursor = event->window;
467 /**********************************************************************
468 * EVENT_ConfigureNotify
470 * The ConfigureNotify event is only selected on the desktop window.
472 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
479 /**********************************************************************
480 * SetCapture (USER.18)
482 HWND SetCapture(HWND wnd)
485 HWND old_capture_wnd = captureWnd;
486 WND *wnd_p = WIN_FindWndPtr(wnd);
490 rv = XGrabPointer(display, wnd_p->window, False,
491 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
492 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
494 if (rv == GrabSuccess)
496 winHasCursor = wnd_p->window;
498 return old_capture_wnd;
504 /**********************************************************************
505 * ReleaseCapture (USER.19)
507 void ReleaseCapture()
509 if (captureWnd == 0) return;
510 XUngrabPointer( display, CurrentTime );
514 /**********************************************************************
515 * GetCapture (USER.236)
523 /**********************************************************************
524 * EnableHardwareInput [USER.331]
526 BOOL EnableHardwareInput(BOOL bEnable)
528 BOOL bOldState = InputEnabled;
529 printf("EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
530 InputEnabled = bEnable;
531 return (bOldState && !bEnable);