Release 941017
[wine/gsoc-2012-control.git] / windows / event.c
blob9da66170d1c1babc3233dc7a905c36756041462e
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"
19 #include "stddebug.h"
20 /* #define DEBUG_EVENT /* */
21 /* #undef DEBUG_EVENT /* */
22 /* #define DEBUG_KEY /* */
23 /* #undef DEBUG_KEY /* */
24 #include "debug.h"
27 #ifdef ndef
28 #ifndef FamilyAmoeba
29 typedef char *XPointer;
30 #endif
31 #endif
33 #ifdef sparc
34 /* Dirty hack to compile with Sun's OpenWindows */
35 typedef char *XPointer;
36 #endif
38 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
40 extern int desktopX, desktopY; /* misc/main.c */
42 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
44 /* X context to associate a hwnd to an X window */
45 static XContext winContext = 0;
47 /* State variables */
48 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
49 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
50 BYTE KeyStateTable[256];
51 BYTE AsyncKeyStateTable[256];
52 static WORD ALTKeyState;
53 static HWND captureWnd = 0;
54 static BOOL InputEnabled = TRUE;
56 /* Keyboard translation tables */
57 static int special_key[] =
59 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
60 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
61 0, 0, 0, VK_ESCAPE /* FF18 */
64 static cursor_key[] =
66 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
67 VK_NEXT, VK_END /* FF50 */
70 static misc_key[] =
72 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
73 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
76 static keypad_key[] =
78 VK_MENU, VK_NUMLOCK, /* FF7E */
79 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
80 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
84 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
85 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
86 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
87 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
88 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
91 static function_key[] =
93 VK_F1, VK_F2, /* FFBE */
94 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
95 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
98 static modifier_key[] =
100 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
101 0, 0, /* FFE1 */
102 0, VK_MENU, VK_MENU /* FFE8 */
105 typedef union
107 struct
109 unsigned long count : 16;
110 unsigned long code : 8;
111 unsigned long extended : 1;
112 unsigned long : 4;
113 unsigned long context : 1;
114 unsigned long previous : 1;
115 unsigned long transition : 1;
116 } lp1;
117 unsigned long lp2;
118 } KEYLP;
120 static BOOL KeyDown = FALSE;
123 static char *event_names[] =
125 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
126 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
127 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
128 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
129 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
130 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
131 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
132 "ClientMessage", "MappingNotify"
135 /* Event handlers */
136 static void EVENT_key( XKeyEvent *event );
137 static void EVENT_ButtonPress( XButtonEvent *event );
138 static void EVENT_ButtonRelease( XButtonEvent *event );
139 static void EVENT_MotionNotify( XMotionEvent *event );
140 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
141 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
142 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
145 /***********************************************************************
146 * EVENT_ProcessEvent
148 * Process an X event.
150 void EVENT_ProcessEvent( XEvent *event )
152 HWND hwnd;
153 XPointer ptr;
155 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
156 hwnd = (HWND) (int)ptr;
158 dprintf_event(stddeb, "Got event %s for hwnd %d\n",
159 event_names[event->type], hwnd );
161 switch(event->type)
163 case KeyPress:
164 case KeyRelease:
165 EVENT_key( (XKeyEvent*)event );
166 break;
168 case ButtonPress:
169 EVENT_ButtonPress( (XButtonEvent*)event );
170 break;
172 case ButtonRelease:
173 EVENT_ButtonRelease( (XButtonEvent*)event );
174 break;
176 case MotionNotify:
177 /* Wine between two fast machines across the overloaded campus
178 ethernet gets very boged down in MotionEvents. The following
179 simply finds the last motion event in the queue and drops
180 the rest. On a good link events are servered before they build
181 up so this doesn't take place. On a slow link this may cause
182 problems if the event order is important. I'm not yet seen
183 of any problems. Jon 7/6/96.
185 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
186 MotionNotify, event));
187 EVENT_MotionNotify( (XMotionEvent*)event );
188 break;
190 case FocusOut:
191 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
192 break;
194 case Expose:
195 EVENT_Expose( hwnd, (XExposeEvent*)event );
196 break;
198 case ConfigureNotify:
199 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
200 break;
202 default:
203 dprintf_event(stddeb, "Unprocessed event %s for hwnd %d\n",
204 event_names[event->type], hwnd );
205 break;
210 /***********************************************************************
211 * EVENT_RegisterWindow
213 * Associate an X window to a HWND.
215 void EVENT_RegisterWindow( Window w, HWND hwnd )
217 if (!winContext) winContext = XUniqueContext();
218 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
222 /***********************************************************************
223 * EVENT_XStateToKeyState
225 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
226 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
228 static WORD EVENT_XStateToKeyState( int state )
230 int kstate = 0;
232 if (state & Button1Mask) kstate |= MK_LBUTTON;
233 if (state & Button2Mask) kstate |= MK_MBUTTON;
234 if (state & Button3Mask) kstate |= MK_RBUTTON;
235 if (state & ShiftMask) kstate |= MK_SHIFT;
236 if (state & ControlMask) kstate |= MK_CONTROL;
237 return kstate;
241 /***********************************************************************
242 * EVENT_Expose
244 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
246 RECT rect;
247 UINT flags;
248 WND * wndPtr = WIN_FindWndPtr( hwnd );
249 if (!wndPtr) return;
251 /* Make position relative to client area instead of window */
252 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
253 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
254 rect.right = rect.left + event->width;
255 rect.bottom = rect.top + event->height;
257 flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN;
258 /* Erase desktop background synchronously */
259 /* if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN; */
260 RedrawWindow( hwnd, &rect, 0, flags );
264 /***********************************************************************
265 * EVENT_key
267 * Handle a X key event
269 static void EVENT_key( XKeyEvent *event )
271 char Str[24];
272 XComposeStatus cs;
273 KeySym keysym;
274 WORD xkey, vkey, key_type, key;
275 KEYLP keylp;
276 BOOL extended = FALSE;
278 int count = XLookupString(event, Str, 1, &keysym, &cs);
279 Str[count] = '\0';
280 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
281 keysym, count, Str[0], Str);
283 xkey = LOWORD(keysym);
284 key_type = HIBYTE(xkey);
285 key = LOBYTE(xkey);
286 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
288 if (key_type == 0xFF) /* non-character key */
290 if (key >= 0x08 && key <= 0x1B) /* special key */
291 vkey = special_key[key - 0x08];
292 else if (key >= 0x50 && key <= 0x57) /* cursor key */
293 vkey = cursor_key[key - 0x50];
294 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
295 vkey = misc_key[key - 0x60];
296 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
298 vkey = keypad_key[key - 0x7E];
299 extended = TRUE;
301 else if (key >= 0xBE && key <= 0xCD) /* function key */
303 vkey = function_key[key - 0xBE];
304 extended = TRUE;
306 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
307 vkey = modifier_key[key - 0xE1];
308 else if (key == 0xFF) /* DEL key */
309 vkey = VK_DELETE;
311 else if (key_type == 0) /* character key */
313 if (key >= 0x61 && key <= 0x7A)
314 vkey = key - 0x20; /* convert lower to uppercase */
315 else
316 vkey = key;
319 if (event->type == KeyPress)
321 if (vkey == VK_MENU) ALTKeyState = TRUE;
322 if (!(KeyStateTable[vkey] & 0x0f))
323 KeyStateTable[vkey] ^= 0x80;
324 KeyStateTable[vkey] |= 0x01;
325 keylp.lp1.count = 1;
326 keylp.lp1.code = LOBYTE(event->keycode);
327 keylp.lp1.extended = (extended ? 1 : 0);
328 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
329 keylp.lp1.previous = (KeyDown ? 0 : 1);
330 keylp.lp1.transition = 0;
331 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
332 vkey, keylp.lp2 );
333 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
334 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
335 vkey, keylp.lp2,
336 event->x_root - desktopX, event->y_root - desktopY,
337 event->time, 0 );
338 KeyDown = TRUE;
340 /* The key translation ought to take place in TranslateMessage().
341 * However, there is no way of passing the required information
342 * in a Windows message, so TranslateMessage does not currently
343 * do anything and the translation is done here.
345 if (count == 1) /* key has an ASCII representation */
347 dprintf_key(stddeb,"WM_CHAR : wParam=%X\n", (WORD)Str[0] );
348 PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
351 else
353 if (vkey == VK_MENU) ALTKeyState = FALSE;
354 KeyStateTable[vkey] &= 0xf0;
355 keylp.lp1.count = 1;
356 keylp.lp1.code = LOBYTE(event->keycode);
357 keylp.lp1.extended = (extended ? 1 : 0);
358 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
359 keylp.lp1.previous = 1;
360 keylp.lp1.transition = 1;
361 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
362 vkey, keylp.lp2 );
363 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
364 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
365 WM_SYSKEYUP : WM_KEYUP),
366 vkey, keylp.lp2,
367 event->x_root - desktopX, event->y_root - desktopY,
368 event->time, 0 );
369 KeyDown = FALSE;
374 /***********************************************************************
375 * EVENT_MotionNotify
377 static void EVENT_MotionNotify( XMotionEvent *event )
379 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
380 event->x_root - desktopX, event->y_root - desktopY,
381 event->time, 0 );
385 /***********************************************************************
386 * EVENT_ButtonPress
388 static void EVENT_ButtonPress( XButtonEvent *event )
390 static WORD messages[NB_BUTTONS] =
391 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
392 int buttonNum = event->button - 1;
394 if (buttonNum >= NB_BUTTONS) return;
395 MouseButtonsStates[buttonNum] = TRUE;
396 AsyncMouseButtonsStates[buttonNum] = TRUE;
397 hardware_event( messages[buttonNum],
398 EVENT_XStateToKeyState( event->state ), 0L,
399 event->x_root - desktopX, event->y_root - desktopY,
400 event->time, 0 );
404 /***********************************************************************
405 * EVENT_ButtonRelease
407 static void EVENT_ButtonRelease( XButtonEvent *event )
409 static const WORD messages[NB_BUTTONS] =
410 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
411 int buttonNum = event->button - 1;
413 if (buttonNum >= NB_BUTTONS) return;
414 MouseButtonsStates[buttonNum] = FALSE;
415 hardware_event( messages[buttonNum],
416 EVENT_XStateToKeyState( event->state ), 0L,
417 event->x_root - desktopX, event->y_root - desktopY,
418 event->time, 0 );
422 /**********************************************************************
423 * EVENT_FocusOut
425 * Note: only top-level override-redirect windows get FocusOut events.
427 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
429 if (event->detail == NotifyPointer) return;
430 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
431 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
435 /**********************************************************************
436 * EVENT_ConfigureNotify
438 * The ConfigureNotify event is only selected on the desktop window.
440 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
442 desktopX = event->x;
443 desktopY = event->y;
447 /**********************************************************************
448 * SetCapture (USER.18)
450 HWND SetCapture( HWND hwnd )
452 Window win;
453 HWND old_capture_wnd = captureWnd;
455 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
456 if (XGrabPointer(display, win, False,
457 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
458 GrabModeAsync, GrabModeAsync,
459 None, None, CurrentTime ) == GrabSuccess)
461 captureWnd = hwnd;
462 return old_capture_wnd;
464 else return 0;
468 /**********************************************************************
469 * ReleaseCapture (USER.19)
471 void ReleaseCapture()
473 if (captureWnd == 0) return;
474 XUngrabPointer( display, CurrentTime );
475 captureWnd = 0;
478 /**********************************************************************
479 * GetCapture (USER.236)
481 HWND GetCapture()
483 return captureWnd;
487 /**********************************************************************
488 * EnableHardwareInput [USER.331]
490 BOOL EnableHardwareInput(BOOL bEnable)
492 BOOL bOldState = InputEnabled;
493 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
494 InputEnabled = bEnable;
495 return (bOldState && !bEnable);