Release 950918
[wine/dcerpc.git] / windows / event.c
blob837d284d9fc87d27286e17f505d29d7ce4468c98
1 /*
2 * X events handling functions
3 *
4 * Copyright 1993 Alexandre Julliard
5 *
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
14 #include <X11/Xatom.h>
15 #include "gdi.h"
16 #include "windows.h"
17 #include "win.h"
18 #include "class.h"
19 #include "message.h"
20 #include "clipboard.h"
21 #include "winpos.h"
22 #include "stddebug.h"
23 /* #define DEBUG_EVENT */
24 /* #define DEBUG_KEY */
25 #include "debug.h"
28 #ifdef ndef
29 #ifndef FamilyAmoeba
30 typedef char *XPointer;
31 #endif
32 #endif
34 #ifdef WHO_NEEDS_DIRTY_HACKS
35 #ifdef sparc
36 /* Dirty hack to compile with Sun's OpenWindows */
37 typedef char *XPointer;
38 #endif
39 #endif
41 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
43 /* X context to associate a hwnd to an X window */
44 static XContext winContext = 0;
46 /* State variables */
47 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
48 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
49 BYTE KeyStateTable[256];
50 BYTE AsyncKeyStateTable[256];
51 static WORD ALTKeyState;
52 static HWND captureWnd = 0;
53 static BOOL InputEnabled = TRUE;
55 /* Keyboard translation tables */
56 static int special_key[] =
58 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
59 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
60 0, 0, 0, VK_ESCAPE /* FF18 */
63 static cursor_key[] =
65 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
66 VK_NEXT, VK_END /* FF50 */
69 static misc_key[] =
71 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
72 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
75 static keypad_key[] =
77 VK_MENU, VK_NUMLOCK, /* FF7E */
78 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
79 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
80 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
83 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
84 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
85 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
86 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
87 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
90 static function_key[] =
92 VK_F1, VK_F2, /* FFBE */
93 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
94 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
97 static modifier_key[] =
99 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
100 0, 0, /* FFE1 */
101 0, VK_MENU, VK_MENU /* FFE8 */
104 typedef union
106 struct
108 unsigned long count : 16;
109 unsigned long code : 8;
110 unsigned long extended : 1;
111 unsigned long : 4;
112 unsigned long context : 1;
113 unsigned long previous : 1;
114 unsigned long transition : 1;
115 } lp1;
116 unsigned long lp2;
117 } KEYLP;
119 static BOOL KeyDown = FALSE;
122 static char *event_names[] =
124 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
125 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
126 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
127 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
128 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
129 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
130 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
131 "ClientMessage", "MappingNotify"
134 /* Event handlers */
135 static void EVENT_key( XKeyEvent *event );
136 static void EVENT_ButtonPress( XButtonEvent *event );
137 static void EVENT_ButtonRelease( XButtonEvent *event );
138 static void EVENT_MotionNotify( XMotionEvent *event );
139 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
140 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
141 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
142 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
143 static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
144 static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
147 /***********************************************************************
148 * EVENT_ProcessEvent
150 * Process an X event.
152 void EVENT_ProcessEvent( XEvent *event )
154 HWND hwnd;
155 XPointer ptr;
157 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
158 hwnd = (HWND) (int)ptr;
160 dprintf_event(stddeb, "Got event %s for hwnd %d\n",
161 event_names[event->type], hwnd );
163 switch(event->type)
165 case KeyPress:
166 case KeyRelease:
167 EVENT_key( (XKeyEvent*)event );
168 break;
170 case ButtonPress:
171 EVENT_ButtonPress( (XButtonEvent*)event );
172 break;
174 case ButtonRelease:
175 EVENT_ButtonRelease( (XButtonEvent*)event );
176 break;
178 case MotionNotify:
179 /* Wine between two fast machines across the overloaded campus
180 ethernet gets very boged down in MotionEvents. The following
181 simply finds the last motion event in the queue and drops
182 the rest. On a good link events are servered before they build
183 up so this doesn't take place. On a slow link this may cause
184 problems if the event order is important. I'm not yet seen
185 of any problems. Jon 7/6/96.
187 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
188 MotionNotify, event));
189 EVENT_MotionNotify( (XMotionEvent*)event );
190 break;
192 case FocusOut:
193 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
194 break;
196 case Expose:
197 EVENT_Expose( hwnd, (XExposeEvent*)event );
198 break;
200 case ConfigureNotify:
201 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
202 break;
204 case SelectionRequest:
205 EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
206 break;
208 case SelectionNotify:
209 EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
210 break;
212 case SelectionClear:
213 EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
214 break;
216 default:
217 dprintf_event(stddeb, "Unprocessed event %s for hwnd %d\n",
218 event_names[event->type], hwnd );
219 break;
224 /***********************************************************************
225 * EVENT_RegisterWindow
227 * Associate an X window to a HWND.
229 void EVENT_RegisterWindow( Window w, HWND hwnd )
231 if (!winContext) winContext = XUniqueContext();
232 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
236 /***********************************************************************
237 * EVENT_XStateToKeyState
239 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
240 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
242 static WORD EVENT_XStateToKeyState( int state )
244 int kstate = 0;
246 if (state & Button1Mask) kstate |= MK_LBUTTON;
247 if (state & Button2Mask) kstate |= MK_MBUTTON;
248 if (state & Button3Mask) kstate |= MK_RBUTTON;
249 if (state & ShiftMask) kstate |= MK_SHIFT;
250 if (state & ControlMask) kstate |= MK_CONTROL;
251 return kstate;
255 /***********************************************************************
256 * EVENT_Expose
258 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
260 RECT rect;
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
262 if (!wndPtr) return;
264 /* Make position relative to client area instead of window */
265 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
266 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
267 rect.right = rect.left + event->width;
268 rect.bottom = rect.top + event->height;
270 RedrawWindow( hwnd, &rect, 0,
271 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
272 (event->count ? 0 : RDW_ERASENOW) );
276 /***********************************************************************
277 * EVENT_key
279 * Handle a X key event
281 static void EVENT_key( XKeyEvent *event )
283 char Str[24];
284 XComposeStatus cs;
285 KeySym keysym;
286 WORD vkey = 0;
287 WORD xkey, key_type, key;
288 KEYLP keylp;
289 BOOL extended = FALSE;
291 int count = XLookupString(event, Str, 1, &keysym, &cs);
292 Str[count] = '\0';
293 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
294 keysym, count, Str[0], Str);
296 xkey = LOWORD(keysym);
297 key_type = HIBYTE(xkey);
298 key = LOBYTE(xkey);
299 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
301 if (key_type == 0xFF) /* non-character key */
303 if (key >= 0x08 && key <= 0x1B) /* special key */
304 vkey = special_key[key - 0x08];
305 else if (key >= 0x50 && key <= 0x57) /* cursor key */
306 vkey = cursor_key[key - 0x50];
307 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
308 vkey = misc_key[key - 0x60];
309 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
311 vkey = keypad_key[key - 0x7E];
312 extended = TRUE;
314 else if (key >= 0xBE && key <= 0xCD) /* function key */
316 vkey = function_key[key - 0xBE];
317 extended = TRUE;
319 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
320 vkey = modifier_key[key - 0xE1];
321 else if (key == 0xFF) /* DEL key */
322 vkey = VK_DELETE;
324 else if (key_type == 0) /* character key */
326 if (isalnum(key))
327 vkey = toupper(key); /* convert lower to uppercase */
328 else
329 vkey = 0xbe;
332 if (event->type == KeyPress)
334 if (vkey == VK_MENU) ALTKeyState = TRUE;
335 if (!(KeyStateTable[vkey] & 0x0f))
336 KeyStateTable[vkey] ^= 0x80;
337 KeyStateTable[vkey] |= 0x01;
338 keylp.lp1.count = 1;
339 keylp.lp1.code = LOBYTE(event->keycode);
340 keylp.lp1.extended = (extended ? 1 : 0);
341 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
342 keylp.lp1.previous = (KeyDown ? 0 : 1);
343 keylp.lp1.transition = 0;
344 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
345 vkey, keylp.lp2 );
346 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
347 hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
348 vkey, keylp.lp2,
349 event->x_root - desktopX, event->y_root - desktopY,
350 event->time, 0 );
351 KeyDown = TRUE;
353 /* The key translation ought to take place in TranslateMessage().
354 * However, there is no way of passing the required information
355 * in a Windows message, so TranslateMessage does not currently
356 * do anything and the translation is done here.
358 if (count == 1) /* key has an ASCII representation */
360 dprintf_key(stddeb,"WM_CHAR : wParam=%X\n", (WORD)Str[0] );
361 PostMessage( GetFocus(), WM_CHAR, (WORD)(unsigned char)(Str[0]),
362 keylp.lp2 );
365 else
367 if (vkey == VK_MENU) ALTKeyState = FALSE;
368 KeyStateTable[vkey] &= 0xf0;
369 keylp.lp1.count = 1;
370 keylp.lp1.code = LOBYTE(event->keycode);
371 keylp.lp1.extended = (extended ? 1 : 0);
372 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
373 keylp.lp1.previous = 1;
374 keylp.lp1.transition = 1;
375 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
376 vkey, keylp.lp2 );
377 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
378 hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
379 WM_SYSKEYUP : WM_KEYUP),
380 vkey, keylp.lp2,
381 event->x_root - desktopX, event->y_root - desktopY,
382 event->time, 0 );
383 KeyDown = FALSE;
388 /***********************************************************************
389 * EVENT_MotionNotify
391 static void EVENT_MotionNotify( XMotionEvent *event )
393 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
394 event->x_root - desktopX, event->y_root - desktopY,
395 event->time, 0 );
399 /***********************************************************************
400 * EVENT_ButtonPress
402 static void EVENT_ButtonPress( XButtonEvent *event )
404 static WORD messages[NB_BUTTONS] =
405 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
406 int buttonNum = event->button - 1;
408 if (buttonNum >= NB_BUTTONS) return;
409 MouseButtonsStates[buttonNum] = TRUE;
410 AsyncMouseButtonsStates[buttonNum] = TRUE;
411 hardware_event( messages[buttonNum],
412 EVENT_XStateToKeyState( event->state ), 0L,
413 event->x_root - desktopX, event->y_root - desktopY,
414 event->time, 0 );
418 /***********************************************************************
419 * EVENT_ButtonRelease
421 static void EVENT_ButtonRelease( XButtonEvent *event )
423 static const WORD messages[NB_BUTTONS] =
424 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
425 int buttonNum = event->button - 1;
427 if (buttonNum >= NB_BUTTONS) return;
428 MouseButtonsStates[buttonNum] = FALSE;
429 hardware_event( messages[buttonNum],
430 EVENT_XStateToKeyState( event->state ), 0L,
431 event->x_root - desktopX, event->y_root - desktopY,
432 event->time, 0 );
436 /**********************************************************************
437 * EVENT_FocusOut
439 * Note: only top-level override-redirect windows get FocusOut events.
441 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
443 if (event->detail == NotifyPointer) return;
444 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
445 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
449 /**********************************************************************
450 * EVENT_ConfigureNotify
452 * The ConfigureNotify event is only selected on the desktop window.
454 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
456 desktopX = event->x;
457 desktopY = event->y;
461 /***********************************************************************
462 * EVENT_SelectionRequest
464 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
466 XSelectionEvent result;
467 Atom rprop;
468 Window request=event->requestor;
469 rprop=None;
470 if(event->target == XA_STRING)
472 HANDLE hText;
473 LPSTR text;
474 rprop=event->property;
475 if(rprop == None)rprop=event->target;
476 if(event->selection!=XA_PRIMARY)rprop=None;
477 else if(!IsClipboardFormatAvailable(CF_TEXT))rprop=None;
478 else{
479 /* Don't worry if we can't open */
480 BOOL couldOpen=OpenClipboard(hwnd);
481 hText=GetClipboardData(CF_TEXT);
482 text=GlobalLock(hText);
483 XChangeProperty(display,request,rprop,XA_STRING,
484 8,PropModeReplace,text,strlen(text));
485 GlobalUnlock(hText);
486 /* close only if we opened before */
487 if(couldOpen)CloseClipboard();
490 if(rprop==None) dprintf_event(stddeb,"Request for %s ignored\n",
491 XGetAtomName(display,event->target));
492 result.type=SelectionNotify;
493 result.display=display;
494 result.requestor=request;
495 result.selection=event->selection;
496 result.property=rprop;
497 result.target=event->target;
498 result.time=event->time;
499 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
503 /***********************************************************************
504 * EVENT_SelectionNotify
506 static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
508 if(event->selection!=XA_PRIMARY)return;
509 if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
510 CLIPBOARD_ReadSelection(event->requestor,event->property);
514 /***********************************************************************
515 * EVENT_SelectionClear
517 static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
519 if(event->selection!=XA_PRIMARY)return;
520 CLIPBOARD_ReleaseSelection(hwnd);
523 /**********************************************************************
524 * SetCapture (USER.18)
526 HWND SetCapture( HWND hwnd )
528 Window win;
529 HWND old_capture_wnd = captureWnd;
531 if (!hwnd)
533 ReleaseCapture();
534 return old_capture_wnd;
536 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
537 if (XGrabPointer(display, win, False,
538 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
539 GrabModeAsync, GrabModeAsync,
540 None, None, CurrentTime ) == GrabSuccess)
542 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
543 captureWnd = hwnd;
544 return old_capture_wnd;
546 else return 0;
550 /**********************************************************************
551 * ReleaseCapture (USER.19)
553 void ReleaseCapture()
555 if (captureWnd == 0) return;
556 XUngrabPointer( display, CurrentTime );
557 captureWnd = 0;
558 dprintf_win(stddeb, "ReleaseCapture\n");
561 /**********************************************************************
562 * GetCapture (USER.236)
564 HWND GetCapture()
566 return captureWnd;
570 /**********************************************************************
571 * EnableHardwareInput [USER.331]
573 BOOL EnableHardwareInput(BOOL bEnable)
575 BOOL bOldState = InputEnabled;
576 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
577 InputEnabled = bEnable;
578 return (bOldState && !bEnable);