Release 940912
[wine/multimedia.git] / windows / event.c
bloba1dd581e3dc3bba2ad110ad46226037dda5f69a3
1 /*
2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
15 #include "windows.h"
16 #include "win.h"
17 #include "class.h"
18 #include "message.h"
20 #ifdef ndef
21 #ifndef FamilyAmoeba
22 typedef char *XPointer;
23 #endif
24 #endif
26 #ifdef sparc
27 /* Dirty hack to compile with Sun's OpenWindows */
28 typedef char *XPointer;
29 #endif
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;
40 /* State variables */
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 */
58 static cursor_key[] =
60 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
61 VK_NEXT, VK_END /* FF50 */
64 static misc_key[] =
66 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
67 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
70 static keypad_key[] =
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,
95 0, 0, /* FFE1 */
96 0, VK_MENU, VK_MENU /* FFE8 */
99 typedef union
101 struct
103 unsigned long count : 16;
104 unsigned long code : 8;
105 unsigned long extended : 1;
106 unsigned long : 4;
107 unsigned long context : 1;
108 unsigned long previous : 1;
109 unsigned long transition : 1;
110 } lp1;
111 unsigned long lp2;
112 } KEYLP;
114 static BOOL KeyDown = FALSE;
117 #ifdef DEBUG_EVENT
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"
129 #endif
131 /* Event handlers */
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 /***********************************************************************
143 * EVENT_ProcessEvent
145 * Process an X event.
147 void EVENT_ProcessEvent( XEvent *event )
149 HWND hwnd;
150 XPointer ptr;
152 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
153 hwnd = (HWND) (int)ptr;
155 #ifdef DEBUG_EVENT
156 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
157 #endif
159 switch(event->type)
161 case KeyPress:
162 case KeyRelease:
163 EVENT_key( hwnd, (XKeyEvent*)event );
164 break;
166 case ButtonPress:
167 EVENT_ButtonPress( (XButtonEvent*)event );
168 break;
170 case ButtonRelease:
171 EVENT_ButtonRelease( (XButtonEvent*)event );
172 break;
174 case MotionNotify:
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 );
186 break;
188 case EnterNotify:
189 EVENT_EnterNotify( (XCrossingEvent*)event );
190 break;
192 case FocusOut:
193 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
194 break;
196 case Expose:
197 EVENT_Expose( hwnd, (XExposeEvent*)event );
198 break;
200 case ConfigureNotify:
201 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
202 break;
204 #ifdef DEBUG_EVENT
205 default:
206 printf( "Unprocessed event %s for hwnd %d\n",
207 event_names[event->type], hwnd );
208 break;
209 #endif
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 )
234 int kstate = 0;
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;
241 return kstate;
245 /***********************************************************************
246 * EVENT_Expose
248 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
250 RECT rect;
251 UINT flags;
252 WND * wndPtr = WIN_FindWndPtr( hwnd );
253 if (!wndPtr) return;
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 /***********************************************************************
270 * EVENT_key
272 * Handle a X key event
274 static void EVENT_key( HWND hwnd, XKeyEvent *event )
276 char Str[24];
277 XComposeStatus cs;
278 KeySym keysym;
279 WORD xkey, vkey, key_type, key;
280 KEYLP keylp;
281 BOOL extended = FALSE;
283 int count = XLookupString(event, Str, 1, &keysym, &cs);
284 Str[count] = '\0';
285 #ifdef DEBUG_KEY
286 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
287 keysym, count, Str[0], Str);
288 #endif
290 xkey = LOWORD(keysym);
291 key_type = HIBYTE(xkey);
292 key = LOBYTE(xkey);
293 #ifdef DEBUG_KEY
294 printf(" key_type=%X, key=%X\n", key_type, key);
295 #endif
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];
308 extended = TRUE;
310 else if (key >= 0xBE && key <= 0xCD) /* function key */
312 vkey = function_key[key - 0xBE];
313 extended = TRUE;
315 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
316 vkey = modifier_key[key - 0xE1];
317 else if (key == 0xFF) /* DEL key */
318 vkey = VK_DELETE;
320 else if (key_type == 0) /* character key */
322 if (key >= 0x61 && key <= 0x7A)
323 vkey = key - 0x20; /* convert lower to uppercase */
324 else
325 vkey = key;
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;
334 keylp.lp1.count = 1;
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;
340 #ifdef DEBUG_KEY
341 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
342 printf(" KeyState=%X\n", KeyStateTable[vkey]);
343 #endif
344 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
345 vkey, keylp.lp2,
346 event->x_root - desktopX, event->y_root - desktopY,
347 event->time, 0 );
348 KeyDown = TRUE;
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 */
357 #ifdef DEBUG_KEY
358 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
359 #endif
360 PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
363 else
365 if (vkey == VK_MENU) ALTKeyState = FALSE;
366 KeyStateTable[vkey] &= 0xf0;
367 keylp.lp1.count = 1;
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 #ifdef DEBUG_KEY
374 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
375 printf(" KeyState=%X\n", KeyStateTable[vkey]);
376 #endif
377 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
378 WM_SYSKEYUP : WM_KEYUP),
379 vkey, keylp.lp2,
380 event->x_root - desktopX, event->y_root - desktopY,
381 event->time, 0 );
382 KeyDown = FALSE;
387 /***********************************************************************
388 * EVENT_MotionNotify
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,
394 event->time, 0 );
398 /***********************************************************************
399 * EVENT_ButtonPress
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,
414 event->time, 0 );
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,
433 event->time, 0 );
437 /**********************************************************************
438 * EVENT_FocusOut
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 /**********************************************************************
451 * EVENT_EnterNotify
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 )
467 desktopX = event->x;
468 desktopY = event->y;
472 /**********************************************************************
473 * SetCapture (USER.18)
475 HWND SetCapture(HWND wnd)
477 int rv;
478 HWND old_capture_wnd = captureWnd;
479 WND *wnd_p = WIN_FindWndPtr(wnd);
480 if (wnd_p == NULL)
481 return 0;
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;
490 captureWnd = wnd;
491 return old_capture_wnd;
493 else
494 return 0;
497 /**********************************************************************
498 * ReleaseCapture (USER.19)
500 void ReleaseCapture()
502 if (captureWnd == 0) return;
503 XUngrabPointer( display, CurrentTime );
504 captureWnd = 0;
507 /**********************************************************************
508 * GetCapture (USER.236)
510 HWND GetCapture()
512 return captureWnd;
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);