Release 940201
[wine.git] / windows / event.c
blob155c66f5e58d96f7d493d9c368077f1cc586dd10
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>
11 #include "windows.h"
12 #include "win.h"
13 #include "class.h"
14 #include "message.h"
17 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
19 extern Display * display;
21 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
23 /* X context to associate a hwnd to an X window */
24 static XContext winContext = 0;
26 /* State variables */
27 static WORD ALTKeyState;
28 static HWND captureWnd = 0;
29 Window winHasCursor = 0;
30 extern HWND hWndFocus;
32 /* Keyboard translation tables */
33 static int special_key[] =
35 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
36 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
37 0, 0, 0, VK_ESCAPE /* FF18 */
40 static cursor_key[] =
42 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
43 VK_NEXT, VK_END /* FF50 */
46 static misc_key[] =
48 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
49 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
52 static keypad_key[] =
54 VK_MENU, VK_NUMLOCK, /* FF7E */
55 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
56 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
57 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
58 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
59 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
60 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
61 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
62 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
63 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
64 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
67 static function_key[] =
69 VK_F1, VK_F2, /* FFBE */
70 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
71 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
74 static modifier_key[] =
76 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
77 0, 0, /* FFE1 */
78 0, VK_MENU, VK_MENU /* FFE8 */
81 typedef union
83 struct
85 unsigned long count : 16;
86 unsigned long code : 8;
87 unsigned long extended : 1;
88 unsigned long : 4;
89 unsigned long context : 1;
90 unsigned long previous : 1;
91 unsigned long transition : 1;
92 } lp1;
93 unsigned long lp2;
94 } KEYLP;
96 static BOOL KeyDown = FALSE;
99 #ifdef DEBUG_EVENT
100 static char *event_names[] =
102 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
103 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
104 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
105 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
106 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
107 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
108 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
109 "ClientMessage", "MappingNotify"
111 #endif
113 /* Event handlers */
114 static void EVENT_key( HWND hwnd, XKeyEvent *event );
115 static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event );
116 static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event );
117 static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event );
118 static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event );
119 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
120 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
121 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
124 /***********************************************************************
125 * EVENT_ProcessEvent
127 * Process an X event.
129 void EVENT_ProcessEvent( XEvent *event )
131 HWND hwnd;
132 XPointer ptr;
134 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
135 hwnd = (HWND) (int)ptr;
137 #ifdef DEBUG_EVENT
138 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
139 #endif
141 switch(event->type)
143 case KeyPress:
144 case KeyRelease:
145 EVENT_key( hwnd, (XKeyEvent*)event );
146 break;
148 case ButtonPress:
149 EVENT_ButtonPress( hwnd, (XButtonEvent*)event );
150 break;
152 case ButtonRelease:
153 EVENT_ButtonRelease( hwnd, (XButtonEvent*)event );
154 break;
156 case MotionNotify:
157 EVENT_MotionNotify( hwnd, (XMotionEvent*)event );
158 break;
160 case EnterNotify:
161 EVENT_EnterNotify( hwnd, (XCrossingEvent*)event );
162 break;
164 case FocusIn:
165 EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
166 break;
168 case FocusOut:
169 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
170 break;
172 case Expose:
173 EVENT_Expose( hwnd, (XExposeEvent*)event );
174 break;
176 #ifdef DEBUG_EVENT
177 default:
178 printf( "Unprocessed event %s for hwnd %d\n",
179 event_names[event->type], hwnd );
180 break;
181 #endif
186 /***********************************************************************
187 * EVENT_RegisterWindow
189 * Associate an X window to a HWND.
191 void EVENT_RegisterWindow( Window w, HWND hwnd )
193 if (!winContext) winContext = XUniqueContext();
194 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
198 /***********************************************************************
199 * EVENT_XStateToKeyState
201 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
202 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
204 static WORD EVENT_XStateToKeyState( int state )
206 int kstate = 0;
208 if (state & Button1Mask) kstate |= MK_LBUTTON;
209 if (state & Button2Mask) kstate |= MK_MBUTTON;
210 if (state & Button3Mask) kstate |= MK_RBUTTON;
211 if (state & ShiftMask) kstate |= MK_SHIFT;
212 if (state & ControlMask) kstate |= MK_CONTROL;
213 return kstate;
217 /***********************************************************************
218 * EVENT_Expose
220 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
222 RECT rect;
223 WND * wndPtr = WIN_FindWndPtr( hwnd );
224 if (!wndPtr) return;
225 /* Make position relative to client area instead of window */
226 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
227 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
228 rect.right = rect.left + event->width;
229 rect.bottom = rect.top + event->height;
230 winHasCursor = event->window;
232 InvalidateRect( hwnd, &rect, TRUE );
236 /***********************************************************************
237 * EVENT_key
239 * Handle a X key event
241 static void EVENT_key( HWND hwnd, XKeyEvent *event )
243 char Str[24];
244 XComposeStatus cs;
245 KeySym keysym;
246 WORD xkey, vkey, key_type, key;
247 KEYLP keylp;
248 BOOL extended = FALSE;
249 WND * wndPtr = WIN_FindWndPtr( hwnd );
250 int count = XLookupString(event, Str, 1, &keysym, &cs);
251 Str[count] = '\0';
252 #ifdef DEBUG_KEY
253 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
254 keysym, count, Str[0], Str);
255 #endif
257 if (wndPtr->dwStyle & WS_DISABLED) {
258 if (event->type == KeyPress) XBell(display, 0);
259 return;
263 xkey = LOWORD(keysym);
264 key_type = HIBYTE(xkey);
265 key = LOBYTE(xkey);
266 #ifdef DEBUG_KEY
267 printf(" key_type=%X, key=%X\n", key_type, key);
268 #endif
270 /* Position must be relative to client area */
271 event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
272 event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
274 if (key_type == 0xFF) /* non-character key */
276 if (key >= 0x08 && key <= 0x1B) /* special key */
277 vkey = special_key[key - 0x08];
278 else if (key >= 0x50 && key <= 0x57) /* cursor key */
279 vkey = cursor_key[key - 0x50];
280 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
281 vkey = misc_key[key - 0x60];
282 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
284 vkey = keypad_key[key - 0x7E];
285 extended = TRUE;
287 else if (key >= 0xBE && key <= 0xCD) /* function key */
289 vkey = function_key[key - 0xBE];
290 extended = TRUE;
292 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
293 vkey = modifier_key[key - 0xE1];
294 else if (key == 0xFF) /* DEL key */
295 vkey = VK_DELETE;
297 else if (key_type == 0) /* character key */
299 if (key >= 0x61 && key <= 0x7A)
300 vkey = key - 0x20; /* convert lower to uppercase */
301 else
302 vkey = key;
305 if (event->type == KeyPress)
307 if (vkey == VK_MENU) ALTKeyState = TRUE;
308 keylp.lp1.count = 1;
309 keylp.lp1.code = LOBYTE(event->keycode);
310 keylp.lp1.extended = (extended ? 1 : 0);
311 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
312 keylp.lp1.previous = (KeyDown ? 0 : 1);
313 keylp.lp1.transition = 0;
314 #ifdef DEBUG_KEY
315 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
316 #endif
317 hardware_event( hwnd, ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
318 vkey, keylp.lp2,
319 event->x_root & 0xffff, event->y_root & 0xffff,
320 event->time, 0 );
321 KeyDown = TRUE;
323 /* The key translation ought to take place in TranslateMessage().
324 * However, there is no way of passing the required information
325 * in a Windows message, so TranslateMessage does not currently
326 * do anything and the translation is done here.
328 if (count == 1) /* key has an ASCII representation */
330 #ifdef DEBUG_KEY
331 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
332 #endif
333 PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
336 else
338 if (vkey == VK_MENU) ALTKeyState = FALSE;
339 keylp.lp1.count = 1;
340 keylp.lp1.code = LOBYTE(event->keycode);
341 keylp.lp1.extended = (extended ? 1 : 0);
342 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
343 keylp.lp1.previous = 1;
344 keylp.lp1.transition = 1;
345 #ifdef DEBUG_KEY
346 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
347 #endif
348 hardware_event( hwnd,
349 ((ALTKeyState || vkey == VK_MENU) ?
350 WM_SYSKEYUP : WM_KEYUP),
351 vkey, keylp.lp2,
352 event->x_root & 0xffff, event->y_root & 0xffff,
353 event->time, 0 );
354 KeyDown = FALSE;
359 /***********************************************************************
360 * EVENT_MotionNotify
362 static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event )
364 WND * wndPtr = WIN_FindWndPtr( hwnd );
366 if (!wndPtr) return;
367 if (wndPtr->dwStyle & WS_DISABLED) {
368 return;
372 hardware_event( hwnd, WM_MOUSEMOVE,
373 EVENT_XStateToKeyState( event->state ), 0L,
374 event->x_root & 0xffff, event->y_root & 0xffff,
375 event->time, 0 );
379 /***********************************************************************
380 * EVENT_ButtonPress
382 static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event )
384 static WORD messages[NB_BUTTONS] =
385 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
386 int buttonNum = event->button - 1;
387 WND * wndPtr = WIN_FindWndPtr( hwnd );
389 if (!wndPtr) {
390 printf("couldn't find window\n");
391 return;
393 if (wndPtr->dwStyle & WS_DISABLED) {
394 XBell(display, 0);
395 return;
400 if (buttonNum >= NB_BUTTONS) return;
401 winHasCursor = event->window;
402 hardware_event( hwnd, messages[buttonNum],
403 EVENT_XStateToKeyState( event->state ), 0L,
404 event->x_root & 0xffff, event->y_root & 0xffff,
405 event->time, 0 );
409 /***********************************************************************
410 * EVENT_ButtonRelease
412 static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event )
414 static const WORD messages[NB_BUTTONS] =
415 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
416 int buttonNum = event->button - 1;
417 WND * wndPtr = WIN_FindWndPtr( hwnd );
419 if (!wndPtr) return;
420 if (wndPtr->dwStyle & WS_DISABLED) {
421 return;
425 if (buttonNum >= NB_BUTTONS) return;
426 winHasCursor = event->window;
427 hardware_event( hwnd, messages[buttonNum],
428 EVENT_XStateToKeyState( event->state ), 0L,
429 event->x_root & 0xffff, event->y_root & 0xffff,
430 event->time, 0 );
434 /**********************************************************************
435 * EVENT_FocusIn
437 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
440 WND * wndPtr = WIN_FindWndPtr( hwnd );
442 if (!wndPtr) return;
443 if (wndPtr->dwStyle & WS_DISABLED) {
444 return;
448 PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
449 hWndFocus = hwnd;
453 /**********************************************************************
454 * EVENT_FocusOut
456 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
458 WND * wndPtr = WIN_FindWndPtr( hwnd );
459 if (!wndPtr) return;
461 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
463 if (wndPtr->dwStyle & WS_DISABLED) {
464 return;
467 if (hWndFocus)
469 PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
470 hWndFocus = 0;
475 /**********************************************************************
476 * EVENT_EnterNotify
478 static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event )
480 WND * wndPtr = WIN_FindWndPtr( hwnd );
482 if (!wndPtr) return;
483 if (wndPtr->dwStyle & WS_DISABLED) {
484 return;
487 if (captureWnd != 0) return;
488 winHasCursor = event->window;
489 /* Simulate a mouse motion to set the correct cursor */
490 hardware_event( hwnd, WM_MOUSEMOVE,
491 EVENT_XStateToKeyState( event->state ), 0L,
492 event->x_root & 0xffff, event->y_root & 0xffff,
493 event->time, 0 );
497 /**********************************************************************
498 * SetCapture (USER.18)
500 HWND SetCapture(HWND wnd)
502 int rv;
503 HWND old_capture_wnd = captureWnd;
504 WND *wnd_p = WIN_FindWndPtr(wnd);
505 if (wnd_p == NULL)
506 return 0;
508 rv = XGrabPointer(display, wnd_p->window, False,
509 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
510 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
512 if (rv == GrabSuccess)
514 captureWnd = wnd;
515 return old_capture_wnd;
517 else
518 return 0;
521 /**********************************************************************
522 * ReleaseCapture (USER.19)
524 void ReleaseCapture()
526 WND *wnd_p;
528 if (captureWnd == 0)
529 return;
531 wnd_p = WIN_FindWndPtr(captureWnd);
532 if (wnd_p == NULL)
533 return;
535 XUngrabPointer( display, CurrentTime );
536 captureWnd = 0;
539 /**********************************************************************
540 * GetCapture (USER.236)
542 HWND GetCapture()
544 return captureWnd;