Release 940510
[wine.git] / windows / event.c
blobf2402b385779bf224e59030fd9db27243c426922
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 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
28 extern int desktopX, desktopY; /* misc/main.c */
30 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
32 /* X context to associate a hwnd to an X window */
33 static XContext winContext = 0;
35 /* State variables */
36 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
37 static WORD ALTKeyState;
38 static HWND captureWnd = 0;
39 Window winHasCursor = 0;
41 /* Keyboard translation tables */
42 static int special_key[] =
44 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
45 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
46 0, 0, 0, VK_ESCAPE /* FF18 */
49 static cursor_key[] =
51 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
52 VK_NEXT, VK_END /* FF50 */
55 static misc_key[] =
57 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
58 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
61 static keypad_key[] =
63 VK_MENU, VK_NUMLOCK, /* FF7E */
64 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
65 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
66 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
67 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
68 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
69 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
70 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
71 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
72 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
73 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
76 static function_key[] =
78 VK_F1, VK_F2, /* FFBE */
79 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
80 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
83 static modifier_key[] =
85 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
86 0, 0, /* FFE1 */
87 0, VK_MENU, VK_MENU /* FFE8 */
90 typedef union
92 struct
94 unsigned long count : 16;
95 unsigned long code : 8;
96 unsigned long extended : 1;
97 unsigned long : 4;
98 unsigned long context : 1;
99 unsigned long previous : 1;
100 unsigned long transition : 1;
101 } lp1;
102 unsigned long lp2;
103 } KEYLP;
105 static BOOL KeyDown = FALSE;
108 #ifdef DEBUG_EVENT
109 static char *event_names[] =
111 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
112 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
113 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
114 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
115 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
116 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
117 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
118 "ClientMessage", "MappingNotify"
120 #endif
122 /* Event handlers */
123 static void EVENT_key( HWND hwnd, XKeyEvent *event );
124 static void EVENT_ButtonPress( XButtonEvent *event );
125 static void EVENT_ButtonRelease( XButtonEvent *event );
126 static void EVENT_MotionNotify( XMotionEvent *event );
127 static void EVENT_EnterNotify( XCrossingEvent *event );
128 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
129 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
130 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
133 /***********************************************************************
134 * EVENT_ProcessEvent
136 * Process an X event.
138 void EVENT_ProcessEvent( XEvent *event )
140 HWND hwnd;
141 XPointer ptr;
143 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
144 hwnd = (HWND) (int)ptr;
146 #ifdef DEBUG_EVENT
147 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
148 #endif
150 switch(event->type)
152 case KeyPress:
153 case KeyRelease:
154 EVENT_key( hwnd, (XKeyEvent*)event );
155 break;
157 case ButtonPress:
158 EVENT_ButtonPress( (XButtonEvent*)event );
159 break;
161 case ButtonRelease:
162 EVENT_ButtonRelease( (XButtonEvent*)event );
163 break;
165 case MotionNotify:
166 EVENT_MotionNotify( (XMotionEvent*)event );
167 break;
169 case EnterNotify:
170 EVENT_EnterNotify( (XCrossingEvent*)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 case ConfigureNotify:
182 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
183 break;
185 #ifdef DEBUG_EVENT
186 default:
187 printf( "Unprocessed event %s for hwnd %d\n",
188 event_names[event->type], hwnd );
189 break;
190 #endif
195 /***********************************************************************
196 * EVENT_RegisterWindow
198 * Associate an X window to a HWND.
200 void EVENT_RegisterWindow( Window w, HWND hwnd )
202 if (!winContext) winContext = XUniqueContext();
203 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
207 /***********************************************************************
208 * EVENT_XStateToKeyState
210 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
211 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
213 static WORD EVENT_XStateToKeyState( int state )
215 int kstate = 0;
217 if (state & Button1Mask) kstate |= MK_LBUTTON;
218 if (state & Button2Mask) kstate |= MK_MBUTTON;
219 if (state & Button3Mask) kstate |= MK_RBUTTON;
220 if (state & ShiftMask) kstate |= MK_SHIFT;
221 if (state & ControlMask) kstate |= MK_CONTROL;
222 return kstate;
226 /***********************************************************************
227 * EVENT_Expose
229 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
231 RECT rect;
232 UINT flags;
233 WND * wndPtr = WIN_FindWndPtr( hwnd );
234 if (!wndPtr) return;
236 /* Make position relative to client area instead of window */
237 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
238 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
239 rect.right = rect.left + event->width;
240 rect.bottom = rect.top + event->height;
241 winHasCursor = event->window;
243 flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
244 /* Erase desktop background synchronously */
245 if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
246 RedrawWindow( hwnd, &rect, 0, flags );
250 /***********************************************************************
251 * EVENT_key
253 * Handle a X key event
255 static void EVENT_key( HWND hwnd, XKeyEvent *event )
257 char Str[24];
258 XComposeStatus cs;
259 KeySym keysym;
260 WORD xkey, vkey, key_type, key;
261 KEYLP keylp;
262 BOOL extended = FALSE;
264 int count = XLookupString(event, Str, 1, &keysym, &cs);
265 Str[count] = '\0';
266 #ifdef DEBUG_KEY
267 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
268 keysym, count, Str[0], Str);
269 #endif
271 xkey = LOWORD(keysym);
272 key_type = HIBYTE(xkey);
273 key = LOBYTE(xkey);
274 #ifdef DEBUG_KEY
275 printf(" key_type=%X, key=%X\n", key_type, key);
276 #endif
278 if (key_type == 0xFF) /* non-character key */
280 if (key >= 0x08 && key <= 0x1B) /* special key */
281 vkey = special_key[key - 0x08];
282 else if (key >= 0x50 && key <= 0x57) /* cursor key */
283 vkey = cursor_key[key - 0x50];
284 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
285 vkey = misc_key[key - 0x60];
286 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
288 vkey = keypad_key[key - 0x7E];
289 extended = TRUE;
291 else if (key >= 0xBE && key <= 0xCD) /* function key */
293 vkey = function_key[key - 0xBE];
294 extended = TRUE;
296 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
297 vkey = modifier_key[key - 0xE1];
298 else if (key == 0xFF) /* DEL key */
299 vkey = VK_DELETE;
301 else if (key_type == 0) /* character key */
303 if (key >= 0x61 && key <= 0x7A)
304 vkey = key - 0x20; /* convert lower to uppercase */
305 else
306 vkey = key;
309 if (event->type == KeyPress)
311 if (vkey == VK_MENU) ALTKeyState = TRUE;
312 keylp.lp1.count = 1;
313 keylp.lp1.code = LOBYTE(event->keycode);
314 keylp.lp1.extended = (extended ? 1 : 0);
315 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
316 keylp.lp1.previous = (KeyDown ? 0 : 1);
317 keylp.lp1.transition = 0;
318 #ifdef DEBUG_KEY
319 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
320 #endif
321 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
322 vkey, keylp.lp2,
323 event->x_root - desktopX, event->y_root - desktopY,
324 event->time, 0 );
325 KeyDown = TRUE;
327 /* The key translation ought to take place in TranslateMessage().
328 * However, there is no way of passing the required information
329 * in a Windows message, so TranslateMessage does not currently
330 * do anything and the translation is done here.
332 if (count == 1) /* key has an ASCII representation */
334 #ifdef DEBUG_KEY
335 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
336 #endif
337 PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
340 else
342 if (vkey == VK_MENU) ALTKeyState = FALSE;
343 keylp.lp1.count = 1;
344 keylp.lp1.code = LOBYTE(event->keycode);
345 keylp.lp1.extended = (extended ? 1 : 0);
346 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
347 keylp.lp1.previous = 1;
348 keylp.lp1.transition = 1;
349 #ifdef DEBUG_KEY
350 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
351 #endif
352 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
353 WM_SYSKEYUP : WM_KEYUP),
354 vkey, keylp.lp2,
355 event->x_root - desktopX, event->y_root - desktopY,
356 event->time, 0 );
357 KeyDown = FALSE;
362 /***********************************************************************
363 * EVENT_MotionNotify
365 static void EVENT_MotionNotify( XMotionEvent *event )
367 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
368 event->x_root - desktopX, event->y_root - desktopY,
369 event->time, 0 );
373 /***********************************************************************
374 * EVENT_ButtonPress
376 static void EVENT_ButtonPress( XButtonEvent *event )
378 static WORD messages[NB_BUTTONS] =
379 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
380 int buttonNum = event->button - 1;
382 if (buttonNum >= NB_BUTTONS) return;
383 MouseButtonsStates[buttonNum] = TRUE;
384 winHasCursor = event->window;
385 hardware_event( messages[buttonNum],
386 EVENT_XStateToKeyState( event->state ), 0L,
387 event->x_root - desktopX, event->y_root - desktopY,
388 event->time, 0 );
392 /***********************************************************************
393 * EVENT_ButtonRelease
395 static void EVENT_ButtonRelease( XButtonEvent *event )
397 static const WORD messages[NB_BUTTONS] =
398 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
399 int buttonNum = event->button - 1;
401 if (buttonNum >= NB_BUTTONS) return;
402 MouseButtonsStates[buttonNum] = FALSE;
403 winHasCursor = event->window;
404 hardware_event( messages[buttonNum],
405 EVENT_XStateToKeyState( event->state ), 0L,
406 event->x_root - desktopX, event->y_root - desktopY,
407 event->time, 0 );
411 /**********************************************************************
412 * EVENT_FocusOut
414 * Note: only top-level override-redirect windows get FocusOut events.
416 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
418 if (event->detail == NotifyPointer) return;
419 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
420 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
424 /**********************************************************************
425 * EVENT_EnterNotify
427 static void EVENT_EnterNotify( XCrossingEvent *event )
429 if (captureWnd != 0) return;
430 winHasCursor = event->window;
434 /**********************************************************************
435 * EVENT_ConfigureNotify
437 * The ConfigureNotify event is only selected on the desktop window.
439 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
441 desktopX = event->x;
442 desktopY = event->y;
446 /**********************************************************************
447 * SetCapture (USER.18)
449 HWND SetCapture(HWND wnd)
451 int rv;
452 HWND old_capture_wnd = captureWnd;
453 WND *wnd_p = WIN_FindWndPtr(wnd);
454 if (wnd_p == NULL)
455 return 0;
457 rv = XGrabPointer(display, wnd_p->window, False,
458 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
459 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
461 if (rv == GrabSuccess)
463 captureWnd = wnd;
464 return old_capture_wnd;
466 else
467 return 0;
470 /**********************************************************************
471 * ReleaseCapture (USER.19)
473 void ReleaseCapture()
475 if (captureWnd == 0) return;
476 XUngrabPointer( display, CurrentTime );
477 captureWnd = 0;
480 /**********************************************************************
481 * GetCapture (USER.236)
483 HWND GetCapture()
485 return captureWnd;