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 /* Make position relative to client area instead of window */
256 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
257 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
258 rect.right = rect.left + event->width;
259 rect.bottom = rect.top + event->height;
260 winHasCursor = event->window;
262 flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
263 /* Erase desktop background synchronously */
264 if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
265 RedrawWindow( hwnd, &rect, 0, flags );
269 /***********************************************************************
272 * Handle a X key event
274 static void EVENT_key( HWND hwnd, XKeyEvent *event )
279 WORD xkey, vkey, key_type, key;
281 BOOL extended = FALSE;
283 int count = XLookupString(event, Str, 1, &keysym, &cs);
286 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
287 keysym, count, Str[0], Str);
290 xkey = LOWORD(keysym);
291 key_type = HIBYTE(xkey);
294 printf(" key_type=%X, key=%X\n", key_type, key);
297 if (key_type == 0xFF) /* non-character key */
299 if (key >= 0x08 && key <= 0x1B) /* special key */
300 vkey = special_key[key - 0x08];
301 else if (key >= 0x50 && key <= 0x57) /* cursor key */
302 vkey = cursor_key[key - 0x50];
303 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
304 vkey = misc_key[key - 0x60];
305 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
307 vkey = keypad_key[key - 0x7E];
310 else if (key >= 0xBE && key <= 0xCD) /* function key */
312 vkey = function_key[key - 0xBE];
315 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
316 vkey = modifier_key[key - 0xE1];
317 else if (key == 0xFF) /* DEL key */
320 else if (key_type == 0) /* character key */
322 if (key >= 0x61 && key <= 0x7A)
323 vkey = key - 0x20; /* convert lower to uppercase */
328 if (event->type == KeyPress)
330 if (vkey == VK_MENU) ALTKeyState = TRUE;
331 if (!(KeyStateTable[vkey] & 0x0f))
332 KeyStateTable[vkey] ^= 0x80;
333 KeyStateTable[vkey] |= 0x01;
335 keylp.lp1.code = LOBYTE(event->keycode);
336 keylp.lp1.extended = (extended ? 1 : 0);
337 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
338 keylp.lp1.previous = (KeyDown ? 0 : 1);
339 keylp.lp1.transition = 0;
341 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
342 printf(" KeyState=%X\n", KeyStateTable[vkey]);
344 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
346 event->x_root - desktopX, event->y_root - desktopY,
350 /* The key translation ought to take place in TranslateMessage().
351 * However, there is no way of passing the required information
352 * in a Windows message, so TranslateMessage does not currently
353 * do anything and the translation is done here.
355 if (count == 1) /* key has an ASCII representation */
358 printf("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;
374 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
375 printf(" KeyState=%X\n", KeyStateTable[vkey]);
377 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
378 WM_SYSKEYUP : WM_KEYUP),
380 event->x_root - desktopX, event->y_root - desktopY,
387 /***********************************************************************
390 static void EVENT_MotionNotify( XMotionEvent *event )
392 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
393 event->x_root - desktopX, event->y_root - desktopY,
398 /***********************************************************************
401 static void EVENT_ButtonPress( XButtonEvent *event )
403 static WORD messages[NB_BUTTONS] =
404 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
405 int buttonNum = event->button - 1;
407 if (buttonNum >= NB_BUTTONS) return;
408 MouseButtonsStates[buttonNum] = TRUE;
409 AsyncMouseButtonsStates[buttonNum] = TRUE;
410 winHasCursor = event->window;
411 hardware_event( messages[buttonNum],
412 EVENT_XStateToKeyState( event->state ), 0L,
413 event->x_root - desktopX, event->y_root - desktopY,
418 /***********************************************************************
419 * EVENT_ButtonRelease
421 static void EVENT_ButtonRelease( XButtonEvent *event )
423 static const WORD messages[NB_BUTTONS] =
424 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
425 int buttonNum = event->button - 1;
427 if (buttonNum >= NB_BUTTONS) return;
428 MouseButtonsStates[buttonNum] = FALSE;
429 winHasCursor = event->window;
430 hardware_event( messages[buttonNum],
431 EVENT_XStateToKeyState( event->state ), 0L,
432 event->x_root - desktopX, event->y_root - desktopY,
437 /**********************************************************************
440 * Note: only top-level override-redirect windows get FocusOut events.
442 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
444 if (event->detail == NotifyPointer) return;
445 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
446 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
450 /**********************************************************************
453 static void EVENT_EnterNotify( XCrossingEvent *event )
455 if (captureWnd != 0) return;
456 winHasCursor = event->window;
460 /**********************************************************************
461 * EVENT_ConfigureNotify
463 * The ConfigureNotify event is only selected on the desktop window.
465 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
472 /**********************************************************************
473 * SetCapture (USER.18)
475 HWND SetCapture(HWND wnd)
478 HWND old_capture_wnd = captureWnd;
479 WND *wnd_p = WIN_FindWndPtr(wnd);
483 rv = XGrabPointer(display, wnd_p->window, False,
484 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
485 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
487 if (rv == GrabSuccess)
489 winHasCursor = wnd_p->window;
491 return old_capture_wnd;
497 /**********************************************************************
498 * ReleaseCapture (USER.19)
500 void ReleaseCapture()
502 if (captureWnd == 0) return;
503 XUngrabPointer( display, CurrentTime );
507 /**********************************************************************
508 * GetCapture (USER.236)
516 /**********************************************************************
517 * EnableHardwareInput [USER.331]
519 BOOL EnableHardwareInput(BOOL bEnable)
521 BOOL bOldState = InputEnabled;
522 printf("EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
523 InputEnabled = bEnable;
524 return (bOldState && !bEnable);