Release 940405
[wine/gsoc-2012-control.git] / windows / event.c
blob887d025331504c8e04b49277beac47844790ec61
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 #ifndef FamilyAmoeba
21 typedef char *XPointer;
22 #endif
24 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
26 extern int desktopX, desktopY; /* misc/main.c */
28 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
30 /* X context to associate a hwnd to an X window */
31 static XContext winContext = 0;
33 /* State variables */
34 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
35 static WORD ALTKeyState;
36 static HWND captureWnd = 0;
37 Window winHasCursor = 0;
39 /* Keyboard translation tables */
40 static int special_key[] =
42 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
43 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
44 0, 0, 0, VK_ESCAPE /* FF18 */
47 static cursor_key[] =
49 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
50 VK_NEXT, VK_END /* FF50 */
53 static misc_key[] =
55 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
56 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
59 static keypad_key[] =
61 VK_MENU, VK_NUMLOCK, /* FF7E */
62 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
63 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
64 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
65 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
66 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
67 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
68 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
69 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
70 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
71 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
74 static function_key[] =
76 VK_F1, VK_F2, /* FFBE */
77 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
78 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
81 static modifier_key[] =
83 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
84 0, 0, /* FFE1 */
85 0, VK_MENU, VK_MENU /* FFE8 */
88 typedef union
90 struct
92 unsigned long count : 16;
93 unsigned long code : 8;
94 unsigned long extended : 1;
95 unsigned long : 4;
96 unsigned long context : 1;
97 unsigned long previous : 1;
98 unsigned long transition : 1;
99 } lp1;
100 unsigned long lp2;
101 } KEYLP;
103 static BOOL KeyDown = FALSE;
106 #ifdef DEBUG_EVENT
107 static char *event_names[] =
109 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
110 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
111 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
112 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
113 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
114 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
115 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
116 "ClientMessage", "MappingNotify"
118 #endif
120 /* Event handlers */
121 static void EVENT_key( HWND hwnd, XKeyEvent *event );
122 static void EVENT_ButtonPress( XButtonEvent *event );
123 static void EVENT_ButtonRelease( XButtonEvent *event );
124 static void EVENT_MotionNotify( XMotionEvent *event );
125 static void EVENT_EnterNotify( XCrossingEvent *event );
126 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
127 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
128 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
131 /***********************************************************************
132 * EVENT_ProcessEvent
134 * Process an X event.
136 void EVENT_ProcessEvent( XEvent *event )
138 HWND hwnd;
139 XPointer ptr;
141 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
142 hwnd = (HWND) (int)ptr;
144 #ifdef DEBUG_EVENT
145 printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
146 #endif
148 switch(event->type)
150 case KeyPress:
151 case KeyRelease:
152 EVENT_key( hwnd, (XKeyEvent*)event );
153 break;
155 case ButtonPress:
156 EVENT_ButtonPress( (XButtonEvent*)event );
157 break;
159 case ButtonRelease:
160 EVENT_ButtonRelease( (XButtonEvent*)event );
161 break;
163 case MotionNotify:
164 EVENT_MotionNotify( (XMotionEvent*)event );
165 break;
167 case EnterNotify:
168 EVENT_EnterNotify( (XCrossingEvent*)event );
169 break;
171 case FocusOut:
172 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
173 break;
175 case Expose:
176 EVENT_Expose( hwnd, (XExposeEvent*)event );
177 break;
179 case ConfigureNotify:
180 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
181 break;
183 #ifdef DEBUG_EVENT
184 default:
185 printf( "Unprocessed event %s for hwnd %d\n",
186 event_names[event->type], hwnd );
187 break;
188 #endif
193 /***********************************************************************
194 * EVENT_RegisterWindow
196 * Associate an X window to a HWND.
198 void EVENT_RegisterWindow( Window w, HWND hwnd )
200 if (!winContext) winContext = XUniqueContext();
201 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
205 /***********************************************************************
206 * EVENT_XStateToKeyState
208 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
209 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
211 static WORD EVENT_XStateToKeyState( int state )
213 int kstate = 0;
215 if (state & Button1Mask) kstate |= MK_LBUTTON;
216 if (state & Button2Mask) kstate |= MK_MBUTTON;
217 if (state & Button3Mask) kstate |= MK_RBUTTON;
218 if (state & ShiftMask) kstate |= MK_SHIFT;
219 if (state & ControlMask) kstate |= MK_CONTROL;
220 return kstate;
224 /***********************************************************************
225 * EVENT_Expose
227 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
229 RECT rect;
230 UINT flags;
231 WND * wndPtr = WIN_FindWndPtr( hwnd );
232 if (!wndPtr) return;
234 /* Make position relative to client area instead of window */
235 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
236 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
237 rect.right = rect.left + event->width;
238 rect.bottom = rect.top + event->height;
239 winHasCursor = event->window;
241 flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
242 /* Erase desktop background synchronously */
243 if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
244 RedrawWindow( hwnd, &rect, 0, flags );
248 /***********************************************************************
249 * EVENT_key
251 * Handle a X key event
253 static void EVENT_key( HWND hwnd, XKeyEvent *event )
255 char Str[24];
256 XComposeStatus cs;
257 KeySym keysym;
258 WORD xkey, vkey, key_type, key;
259 KEYLP keylp;
260 BOOL extended = FALSE;
262 int count = XLookupString(event, Str, 1, &keysym, &cs);
263 Str[count] = '\0';
264 #ifdef DEBUG_KEY
265 printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
266 keysym, count, Str[0], Str);
267 #endif
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 if (key_type == 0xFF) /* non-character key */
278 if (key >= 0x08 && key <= 0x1B) /* special key */
279 vkey = special_key[key - 0x08];
280 else if (key >= 0x50 && key <= 0x57) /* cursor key */
281 vkey = cursor_key[key - 0x50];
282 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
283 vkey = misc_key[key - 0x60];
284 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
286 vkey = keypad_key[key - 0x7E];
287 extended = TRUE;
289 else if (key >= 0xBE && key <= 0xCD) /* function key */
291 vkey = function_key[key - 0xBE];
292 extended = TRUE;
294 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
295 vkey = modifier_key[key - 0xE1];
296 else if (key == 0xFF) /* DEL key */
297 vkey = VK_DELETE;
299 else if (key_type == 0) /* character key */
301 if (key >= 0x61 && key <= 0x7A)
302 vkey = key - 0x20; /* convert lower to uppercase */
303 else
304 vkey = key;
307 if (event->type == KeyPress)
309 if (vkey == VK_MENU) ALTKeyState = TRUE;
310 keylp.lp1.count = 1;
311 keylp.lp1.code = LOBYTE(event->keycode);
312 keylp.lp1.extended = (extended ? 1 : 0);
313 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
314 keylp.lp1.previous = (KeyDown ? 0 : 1);
315 keylp.lp1.transition = 0;
316 #ifdef DEBUG_KEY
317 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
318 #endif
319 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
320 vkey, keylp.lp2,
321 event->x_root - desktopX, event->y_root - desktopY,
322 event->time, 0 );
323 KeyDown = TRUE;
325 /* The key translation ought to take place in TranslateMessage().
326 * However, there is no way of passing the required information
327 * in a Windows message, so TranslateMessage does not currently
328 * do anything and the translation is done here.
330 if (count == 1) /* key has an ASCII representation */
332 #ifdef DEBUG_KEY
333 printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
334 #endif
335 PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
338 else
340 if (vkey == VK_MENU) ALTKeyState = FALSE;
341 keylp.lp1.count = 1;
342 keylp.lp1.code = LOBYTE(event->keycode);
343 keylp.lp1.extended = (extended ? 1 : 0);
344 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
345 keylp.lp1.previous = 1;
346 keylp.lp1.transition = 1;
347 #ifdef DEBUG_KEY
348 printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
349 #endif
350 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
351 WM_SYSKEYUP : WM_KEYUP),
352 vkey, keylp.lp2,
353 event->x_root - desktopX, event->y_root - desktopY,
354 event->time, 0 );
355 KeyDown = FALSE;
360 /***********************************************************************
361 * EVENT_MotionNotify
363 static void EVENT_MotionNotify( XMotionEvent *event )
365 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
366 event->x_root - desktopX, event->y_root - desktopY,
367 event->time, 0 );
371 /***********************************************************************
372 * EVENT_ButtonPress
374 static void EVENT_ButtonPress( XButtonEvent *event )
376 static WORD messages[NB_BUTTONS] =
377 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
378 int buttonNum = event->button - 1;
380 if (buttonNum >= NB_BUTTONS) return;
381 MouseButtonsStates[buttonNum] = TRUE;
382 winHasCursor = event->window;
383 hardware_event( messages[buttonNum],
384 EVENT_XStateToKeyState( event->state ), 0L,
385 event->x_root - desktopX, event->y_root - desktopY,
386 event->time, 0 );
390 /***********************************************************************
391 * EVENT_ButtonRelease
393 static void EVENT_ButtonRelease( XButtonEvent *event )
395 static const WORD messages[NB_BUTTONS] =
396 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
397 int buttonNum = event->button - 1;
399 if (buttonNum >= NB_BUTTONS) return;
400 MouseButtonsStates[buttonNum] = FALSE;
401 winHasCursor = event->window;
402 hardware_event( messages[buttonNum],
403 EVENT_XStateToKeyState( event->state ), 0L,
404 event->x_root - desktopX, event->y_root - desktopY,
405 event->time, 0 );
409 /**********************************************************************
410 * EVENT_FocusOut
412 * Note: only top-level override-redirect windows get FocusOut events.
414 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
416 if (event->detail == NotifyPointer) return;
417 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
418 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
422 /**********************************************************************
423 * EVENT_EnterNotify
425 static void EVENT_EnterNotify( XCrossingEvent *event )
427 if (captureWnd != 0) return;
428 winHasCursor = event->window;
432 /**********************************************************************
433 * EVENT_ConfigureNotify
435 * The ConfigureNotify event is only selected on the desktop window.
437 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
439 desktopX = event->x;
440 desktopY = event->y;
444 /**********************************************************************
445 * SetCapture (USER.18)
447 HWND SetCapture(HWND wnd)
449 int rv;
450 HWND old_capture_wnd = captureWnd;
451 WND *wnd_p = WIN_FindWndPtr(wnd);
452 if (wnd_p == NULL)
453 return 0;
455 rv = XGrabPointer(display, wnd_p->window, False,
456 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
457 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
459 if (rv == GrabSuccess)
461 captureWnd = wnd;
462 return old_capture_wnd;
464 else
465 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;