Release 940301
[wine/multimedia.git] / windows / event.c
blob87c0229a2409b7fd1238a668d5d6a82f764580d6
1 /*
2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Xlib.h>
10 #include <X11/Xresource.h>
11 #include <X11/Xutil.h>
13 #include "windows.h"
14 #include "win.h"
15 #include "class.h"
16 #include "message.h"
18 #ifndef FamilyAmoeba
19 typedef char *XPointer;
20 #endif
22 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
24 extern Display * display;
26 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
28 /* X context to associate a hwnd to an X window */
29 static XContext winContext = 0;
31 /* State variables */
32 static WORD ALTKeyState;
33 static HWND captureWnd = 0;
34 Window winHasCursor = 0;
35 extern HWND hWndFocus;
37 /* Keyboard translation tables */
38 static int special_key[] =
40 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
41 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
42 0, 0, 0, VK_ESCAPE /* FF18 */
45 static cursor_key[] =
47 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
48 VK_NEXT, VK_END /* FF50 */
51 static misc_key[] =
53 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
54 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
57 static keypad_key[] =
59 VK_MENU, VK_NUMLOCK, /* FF7E */
60 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
61 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
62 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
63 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
64 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
65 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
66 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
67 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
68 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
69 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
72 static function_key[] =
74 VK_F1, VK_F2, /* FFBE */
75 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
76 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
79 static modifier_key[] =
81 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
82 0, 0, /* FFE1 */
83 0, VK_MENU, VK_MENU /* FFE8 */
86 typedef union
88 struct
90 unsigned long count : 16;
91 unsigned long code : 8;
92 unsigned long extended : 1;
93 unsigned long : 4;
94 unsigned long context : 1;
95 unsigned long previous : 1;
96 unsigned long transition : 1;
97 } lp1;
98 unsigned long lp2;
99 } KEYLP;
101 static BOOL KeyDown = FALSE;
104 #ifdef DEBUG_EVENT
105 static char *event_names[] =
107 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
108 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
109 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
110 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
111 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
112 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
113 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
114 "ClientMessage", "MappingNotify"
116 #endif
118 /* Event handlers */
119 static void EVENT_key( HWND hwnd, XKeyEvent *event );
120 static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event );
121 static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event );
122 static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event );
123 static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event );
124 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
125 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
126 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
129 /***********************************************************************
130 * EVENT_ProcessEvent
132 * Process an X event.
134 void EVENT_ProcessEvent( XEvent *event )
136 HWND hwnd;
137 XPointer ptr;
139 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
140 hwnd = (HWND) (int)ptr;
142 #ifdef DEBUG_EVENT
143 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
144 #endif
146 switch(event->type)
148 case KeyPress:
149 case KeyRelease:
150 EVENT_key( hwnd, (XKeyEvent*)event );
151 break;
153 case ButtonPress:
154 EVENT_ButtonPress( hwnd, (XButtonEvent*)event );
155 break;
157 case ButtonRelease:
158 EVENT_ButtonRelease( hwnd, (XButtonEvent*)event );
159 break;
161 case MotionNotify:
162 EVENT_MotionNotify( hwnd, (XMotionEvent*)event );
163 break;
165 case EnterNotify:
166 EVENT_EnterNotify( hwnd, (XCrossingEvent*)event );
167 break;
169 case FocusIn:
170 EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
171 break;
173 case FocusOut:
174 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
175 break;
177 case Expose:
178 EVENT_Expose( hwnd, (XExposeEvent*)event );
179 break;
181 #ifdef DEBUG_EVENT
182 default:
183 printf( "Unprocessed event %s for hwnd %d\n",
184 event_names[event->type], hwnd );
185 break;
186 #endif
191 /***********************************************************************
192 * EVENT_RegisterWindow
194 * Associate an X window to a HWND.
196 void EVENT_RegisterWindow( Window w, HWND hwnd )
198 if (!winContext) winContext = XUniqueContext();
199 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
203 /***********************************************************************
204 * EVENT_XStateToKeyState
206 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
207 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
209 static WORD EVENT_XStateToKeyState( int state )
211 int kstate = 0;
213 if (state & Button1Mask) kstate |= MK_LBUTTON;
214 if (state & Button2Mask) kstate |= MK_MBUTTON;
215 if (state & Button3Mask) kstate |= MK_RBUTTON;
216 if (state & ShiftMask) kstate |= MK_SHIFT;
217 if (state & ControlMask) kstate |= MK_CONTROL;
218 return kstate;
222 /***********************************************************************
223 * EVENT_Expose
225 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
227 RECT rect;
228 WND * wndPtr = WIN_FindWndPtr( hwnd );
229 if (!wndPtr) return;
230 /* Make position relative to client area instead of window */
231 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
232 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
233 rect.right = rect.left + event->width;
234 rect.bottom = rect.top + event->height;
235 winHasCursor = event->window;
237 RedrawWindow( hwnd, &rect, 0,
238 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_NOCHILDREN );
242 /***********************************************************************
243 * EVENT_key
245 * Handle a X key event
247 static void EVENT_key( HWND hwnd, XKeyEvent *event )
249 char Str[24];
250 XComposeStatus cs;
251 KeySym keysym;
252 WORD xkey, vkey, key_type, key;
253 KEYLP keylp;
254 BOOL extended = FALSE;
255 WND * wndPtr = WIN_FindWndPtr( hwnd );
256 int count = XLookupString(event, Str, 1, &keysym, &cs);
257 Str[count] = '\0';
258 #ifdef DEBUG_KEY
259 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
260 keysym, count, Str[0], Str);
261 #endif
263 if (wndPtr->dwStyle & WS_DISABLED) {
264 if (event->type == KeyPress) XBell(display, 0);
265 return;
269 xkey = LOWORD(keysym);
270 key_type = HIBYTE(xkey);
271 key = LOBYTE(xkey);
272 #ifdef DEBUG_KEY
273 printf(" key_type=%X, key=%X\n", key_type, key);
274 #endif
276 /* Position must be relative to client area */
277 event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
278 event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
280 if (key_type == 0xFF) /* non-character key */
282 if (key >= 0x08 && key <= 0x1B) /* special key */
283 vkey = special_key[key - 0x08];
284 else if (key >= 0x50 && key <= 0x57) /* cursor key */
285 vkey = cursor_key[key - 0x50];
286 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
287 vkey = misc_key[key - 0x60];
288 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
290 vkey = keypad_key[key - 0x7E];
291 extended = TRUE;
293 else if (key >= 0xBE && key <= 0xCD) /* function key */
295 vkey = function_key[key - 0xBE];
296 extended = TRUE;
298 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
299 vkey = modifier_key[key - 0xE1];
300 else if (key == 0xFF) /* DEL key */
301 vkey = VK_DELETE;
303 else if (key_type == 0) /* character key */
305 if (key >= 0x61 && key <= 0x7A)
306 vkey = key - 0x20; /* convert lower to uppercase */
307 else
308 vkey = key;
311 if (event->type == KeyPress)
313 if (vkey == VK_MENU) ALTKeyState = TRUE;
314 keylp.lp1.count = 1;
315 keylp.lp1.code = LOBYTE(event->keycode);
316 keylp.lp1.extended = (extended ? 1 : 0);
317 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
318 keylp.lp1.previous = (KeyDown ? 0 : 1);
319 keylp.lp1.transition = 0;
320 #ifdef DEBUG_KEY
321 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
322 #endif
323 hardware_event( hwnd, ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
324 vkey, keylp.lp2,
325 event->x_root & 0xffff, event->y_root & 0xffff,
326 event->time, 0 );
327 KeyDown = TRUE;
329 /* The key translation ought to take place in TranslateMessage().
330 * However, there is no way of passing the required information
331 * in a Windows message, so TranslateMessage does not currently
332 * do anything and the translation is done here.
334 if (count == 1) /* key has an ASCII representation */
336 #ifdef DEBUG_KEY
337 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
338 #endif
339 PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
342 else
344 if (vkey == VK_MENU) ALTKeyState = FALSE;
345 keylp.lp1.count = 1;
346 keylp.lp1.code = LOBYTE(event->keycode);
347 keylp.lp1.extended = (extended ? 1 : 0);
348 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
349 keylp.lp1.previous = 1;
350 keylp.lp1.transition = 1;
351 #ifdef DEBUG_KEY
352 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
353 #endif
354 hardware_event( hwnd,
355 ((ALTKeyState || vkey == VK_MENU) ?
356 WM_SYSKEYUP : WM_KEYUP),
357 vkey, keylp.lp2,
358 event->x_root & 0xffff, event->y_root & 0xffff,
359 event->time, 0 );
360 KeyDown = FALSE;
365 /***********************************************************************
366 * EVENT_MotionNotify
368 static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event )
370 WND * wndPtr = WIN_FindWndPtr( hwnd );
372 if (!wndPtr) return;
373 if (wndPtr->dwStyle & WS_DISABLED) {
374 return;
378 hardware_event( hwnd, WM_MOUSEMOVE,
379 EVENT_XStateToKeyState( event->state ), 0L,
380 event->x_root & 0xffff, event->y_root & 0xffff,
381 event->time, 0 );
385 /***********************************************************************
386 * EVENT_ButtonPress
388 static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event )
390 static WORD messages[NB_BUTTONS] =
391 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
392 int buttonNum = event->button - 1;
393 WND * wndPtr = WIN_FindWndPtr( hwnd );
395 if (!wndPtr) {
396 printf("couldn't find window\n");
397 return;
399 if (wndPtr->dwStyle & WS_DISABLED) {
400 XBell(display, 0);
401 return;
406 if (buttonNum >= NB_BUTTONS) return;
407 winHasCursor = event->window;
408 hardware_event( hwnd, messages[buttonNum],
409 EVENT_XStateToKeyState( event->state ), 0L,
410 event->x_root & 0xffff, event->y_root & 0xffff,
411 event->time, 0 );
415 /***********************************************************************
416 * EVENT_ButtonRelease
418 static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event )
420 static const WORD messages[NB_BUTTONS] =
421 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
422 int buttonNum = event->button - 1;
423 WND * wndPtr = WIN_FindWndPtr( hwnd );
425 if (!wndPtr) return;
426 if (wndPtr->dwStyle & WS_DISABLED) {
427 return;
431 if (buttonNum >= NB_BUTTONS) return;
432 winHasCursor = event->window;
433 hardware_event( hwnd, messages[buttonNum],
434 EVENT_XStateToKeyState( event->state ), 0L,
435 event->x_root & 0xffff, event->y_root & 0xffff,
436 event->time, 0 );
440 /**********************************************************************
441 * EVENT_FocusIn
443 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
446 WND * wndPtr = WIN_FindWndPtr( hwnd );
448 if (!wndPtr) return;
449 if (wndPtr->dwStyle & WS_DISABLED) {
450 return;
454 PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
455 hWndFocus = hwnd;
459 /**********************************************************************
460 * EVENT_FocusOut
462 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
464 WND * wndPtr = WIN_FindWndPtr( hwnd );
465 if (!wndPtr) return;
467 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
469 if (wndPtr->dwStyle & WS_DISABLED) {
470 return;
473 if (hWndFocus)
475 PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
476 hWndFocus = 0;
481 /**********************************************************************
482 * EVENT_EnterNotify
484 static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event )
486 WND * wndPtr = WIN_FindWndPtr( hwnd );
488 if (!wndPtr) return;
489 if (wndPtr->dwStyle & WS_DISABLED) {
490 return;
493 if (captureWnd != 0) return;
494 winHasCursor = event->window;
495 /* Simulate a mouse motion to set the correct cursor */
496 hardware_event( hwnd, WM_MOUSEMOVE,
497 EVENT_XStateToKeyState( event->state ), 0L,
498 event->x_root & 0xffff, event->y_root & 0xffff,
499 event->time, 0 );
503 /**********************************************************************
504 * SetCapture (USER.18)
506 HWND SetCapture(HWND wnd)
508 int rv;
509 HWND old_capture_wnd = captureWnd;
510 WND *wnd_p = WIN_FindWndPtr(wnd);
511 if (wnd_p == NULL)
512 return 0;
514 rv = XGrabPointer(display, wnd_p->window, False,
515 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
516 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
518 if (rv == GrabSuccess)
520 captureWnd = wnd;
521 return old_capture_wnd;
523 else
524 return 0;
527 /**********************************************************************
528 * ReleaseCapture (USER.19)
530 void ReleaseCapture()
532 WND *wnd_p;
534 if (captureWnd == 0)
535 return;
537 wnd_p = WIN_FindWndPtr(captureWnd);
538 if (wnd_p == NULL)
539 return;
541 XUngrabPointer( display, CurrentTime );
542 captureWnd = 0;
545 /**********************************************************************
546 * GetCapture (USER.236)
548 HWND GetCapture()
550 return captureWnd;