Release 970112
[wine.git] / windows / event.c
blob19480dda7a6084286635f6dd2c490e570ffa371a
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 <string.h>
12 #include <unistd.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <errno.h>
16 #include <X11/keysym.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
22 #include "windows.h"
23 #include "winnt.h"
24 #include "gdi.h"
25 #include "heap.h"
26 #include "queue.h"
27 #include "win.h"
28 #include "class.h"
29 #include "clipboard.h"
30 #include "message.h"
31 #include "module.h"
32 #include "options.h"
33 #include "queue.h"
34 #include "winpos.h"
35 #include "drive.h"
36 #include "shell.h"
37 #include "xmalloc.h"
38 #include "keyboard.h"
39 #include "stddebug.h"
40 #include "debug.h"
41 #include "dde_proc.h"
44 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
46 #define DndNotDnd -1 /* OffiX drag&drop */
47 #define DndUnknown 0
48 #define DndRawData 1
49 #define DndFile 2
50 #define DndFiles 3
51 #define DndText 4
52 #define DndDir 5
53 #define DndLink 6
54 #define DndExe 7
56 #define DndEND 8
58 /* X context to associate a hwnd to an X window */
59 static XContext winContext = 0;
61 /* State variables */
62 BOOL MouseButtonsStates[NB_BUTTONS];
63 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
64 BYTE InputKeyStateTable[256];
66 static INT16 captureHT = HTCLIENT;
67 static HWND32 captureWnd = 0;
68 static BOOL32 InputEnabled = TRUE;
70 static Atom wmProtocols = None;
71 static Atom wmDeleteWindow = None;
72 static Atom dndProtocol = None;
73 static Atom dndSelection = None;
75 static const char * const event_names[] =
77 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
78 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
79 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
80 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
81 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
82 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
83 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
84 "ClientMessage", "MappingNotify"
87 /* Event handlers */
88 static void EVENT_key( XKeyEvent *event );
89 static void EVENT_ButtonPress( XButtonEvent *event );
90 static void EVENT_ButtonRelease( XButtonEvent *event );
91 static void EVENT_MotionNotify( XMotionEvent *event );
92 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
93 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
94 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
95 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
96 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
97 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
98 static void EVENT_SelectionNotify( XSelectionEvent *event);
99 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
100 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
101 static void EVENT_MapNotify( HWND hwnd, XMapEvent *event );
103 /* Usable only with OLVWM - compile option perhaps?
104 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
107 extern void FOCUS_SetXFocus( HWND32 );
108 extern BOOL16 DRAG_QueryUpdate( HWND, SEGPTR, BOOL32 );
110 /***********************************************************************
111 * EVENT_ProcessEvent
113 * Process an X event.
115 void EVENT_ProcessEvent( XEvent *event )
117 WND *pWnd;
119 if (XFindContext( display, event->xany.window, winContext,
120 (char **)&pWnd ) != 0)
121 return; /* Not for a registered window */
123 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
124 event_names[event->type], pWnd->hwndSelf );
126 switch(event->type)
128 case KeyPress:
129 case KeyRelease:
130 if (InputEnabled)
131 EVENT_key( (XKeyEvent*)event );
132 break;
134 case ButtonPress:
135 if (InputEnabled)
136 EVENT_ButtonPress( (XButtonEvent*)event );
137 break;
139 case ButtonRelease:
140 if (InputEnabled)
141 EVENT_ButtonRelease( (XButtonEvent*)event );
142 break;
144 case MotionNotify:
145 /* Wine between two fast machines across the overloaded campus
146 ethernet gets very boged down in MotionEvents. The following
147 simply finds the last motion event in the queue and drops
148 the rest. On a good link events are servered before they build
149 up so this doesn't take place. On a slow link this may cause
150 problems if the event order is important. I'm not yet seen
151 of any problems. Jon 7/6/96.
153 if (InputEnabled)
155 while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
156 MotionNotify, event));
157 EVENT_MotionNotify( (XMotionEvent*)event );
159 break;
161 case FocusIn:
162 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
163 break;
165 case FocusOut:
166 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
167 break;
169 case Expose:
170 EVENT_Expose( pWnd, (XExposeEvent *)event );
171 break;
173 case GraphicsExpose:
174 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
175 break;
177 case ConfigureNotify:
178 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
179 break;
181 case SelectionRequest:
182 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
183 break;
185 case SelectionNotify:
186 EVENT_SelectionNotify( (XSelectionEvent *)event );
187 break;
189 case SelectionClear:
190 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
191 break;
193 case ClientMessage:
194 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
195 break;
197 /* case EnterNotify:
198 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
199 * break;
201 case NoExpose:
202 break;
204 /* We get all these because of StructureNotifyMask. */
205 case UnmapNotify:
206 case CirculateNotify:
207 case CreateNotify:
208 case DestroyNotify:
209 case GravityNotify:
210 case ReparentNotify:
211 break;
213 case MapNotify:
214 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
215 break;
217 default:
218 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
219 event_names[event->type], pWnd->hwndSelf );
220 break;
225 /***********************************************************************
226 * EVENT_RegisterWindow
228 * Associate an X window to a HWND.
230 void EVENT_RegisterWindow( WND *pWnd )
232 if (wmProtocols == None)
233 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
234 if (wmDeleteWindow == None)
235 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
236 if( dndProtocol == None )
237 dndProtocol = XInternAtom( display, "DndProtocol" , False );
238 if( dndSelection == None )
239 dndSelection = XInternAtom( display, "DndSelection" , False );
241 XSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
243 if (!winContext) winContext = XUniqueContext();
244 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
247 /***********************************************************************
248 * EVENT_DestroyWindow
250 void EVENT_DestroyWindow( WND *pWnd )
252 XEvent xe;
254 XDeleteContext( display, pWnd->window, winContext );
255 XDestroyWindow( display, pWnd->window );
256 while( XCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
259 /***********************************************************************
260 * EVENT_WaitXEvent
262 * Wait for an X event, optionally sleeping until one arrives.
263 * Return TRUE if an event is pending, FALSE on timeout or error
264 * (for instance lost connection with the server).
266 BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek )
268 XEvent event;
269 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
271 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
272 * in this case, we fall through directly to the XNextEvent loop.
275 if ((maxWait != -1) && !XPending(display))
277 fd_set read_set;
278 struct timeval timeout;
279 int fd = ConnectionNumber(display);
281 FD_ZERO( &read_set );
282 FD_SET( fd, &read_set );
284 timeout.tv_usec = (maxWait % 1000) * 1000;
285 timeout.tv_sec = maxWait / 1000;
287 #ifdef CONFIG_IPC
288 sigsetjmp(env_wait_x, 1);
289 stop_wait_op= CONT;
291 if (DDE_GetRemoteMessage()) {
292 while(DDE_GetRemoteMessage())
294 return TRUE;
296 stop_wait_op = STOP_WAIT_X;
297 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
298 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
299 !XPending(display))
301 stop_wait_op = CONT;
302 TIMER_ExpireTimers();
303 return FALSE;
305 else stop_wait_op = CONT;
306 #else /* CONFIG_IPC */
307 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
309 /* Timeout or error */
310 TIMER_ExpireTimers();
311 return FALSE;
313 #endif /* CONFIG_IPC */
317 /* Process the event (and possibly others that occurred in the meantime) */
322 #ifdef CONFIG_IPC
323 if (DDE_GetRemoteMessage())
325 while(DDE_GetRemoteMessage()) ;
326 return TRUE;
328 #endif /* CONFIG_IPC */
330 XNextEvent( display, &event );
332 if( peek )
334 WND* pWnd;
335 MESSAGEQUEUE* pQ;
337 if (XFindContext( display, ((XAnyEvent *)&event)->window, winContext,
338 (char **)&pWnd ) || (event.type == NoExpose))
339 continue;
341 /* check for the "safe" hardware events */
343 if( event.type == MotionNotify ||
344 event.type == ButtonPress || event.type == ButtonRelease ||
345 event.type == KeyPress || event.type == KeyRelease ||
346 event.type == SelectionRequest || event.type == SelectionClear )
348 EVENT_ProcessEvent( &event );
349 continue;
352 if( pWnd )
353 if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
355 pQ->flags |= QUEUE_FLAG_XEVENT;
356 PostEvent(pQ->hTask);
357 XPutBackEvent(display, &event);
358 break;
361 else
362 EVENT_ProcessEvent( &event );
364 while (XPending( display ));
365 return TRUE;
369 /***********************************************************************
370 * EVENT_Synchronize
372 * Synchronize with the X server. Should not be used too often.
374 void EVENT_Synchronize()
376 XEvent event;
378 XSync( display, False );
379 while (XPending( display ))
381 XNextEvent( display, &event );
382 EVENT_ProcessEvent( &event );
387 /***********************************************************************
388 * EVENT_XStateToKeyState
390 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
391 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
393 static WORD EVENT_XStateToKeyState( int state )
395 int kstate = 0;
397 if (state & Button1Mask) kstate |= MK_LBUTTON;
398 if (state & Button2Mask) kstate |= MK_MBUTTON;
399 if (state & Button3Mask) kstate |= MK_RBUTTON;
400 if (state & ShiftMask) kstate |= MK_SHIFT;
401 if (state & ControlMask) kstate |= MK_CONTROL;
402 return kstate;
406 /***********************************************************************
407 * EVENT_Expose
409 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
411 RECT32 rect;
413 /* Make position relative to client area instead of window */
414 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
415 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
416 rect.right = rect.left + event->width;
417 rect.bottom = rect.top + event->height;
419 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
420 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
421 (event->count ? 0 : RDW_ERASENOW), 0 );
425 /***********************************************************************
426 * EVENT_GraphicsExpose
428 * This is needed when scrolling area is partially obscured
429 * by non-Wine X window.
431 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
433 RECT32 rect;
435 /* Make position relative to client area instead of window */
436 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
437 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
438 rect.right = rect.left + event->width;
439 rect.bottom = rect.top + event->height;
441 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
442 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
443 (event->count ? 0 : RDW_ERASENOW), 0 );
447 /***********************************************************************
448 * EVENT_key
450 * Handle a X key event
453 /* Keyboard translation tables */
454 static const int special_key[] =
456 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
457 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
458 0, 0, 0, VK_ESCAPE /* FF18 */
461 static const int cursor_key[] =
463 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
464 VK_NEXT, VK_END /* FF50 */
467 static const int misc_key[] =
469 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
470 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
473 static const int keypad_key[] =
475 0, VK_NUMLOCK, /* FF7E */
476 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
477 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
478 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
479 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
480 VK_INSERT, VK_DELETE, /* FF98 */
481 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
482 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
483 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
484 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
485 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
486 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
489 static const int function_key[] =
491 VK_F1, VK_F2, /* FFBE */
492 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
493 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
496 static const int modifier_key[] =
498 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
499 VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
502 static int AltGrMask;
503 static int min_keycode, max_keycode;
504 static int keyc2vkey [256];
505 /* For example : keyc2vkey[10] is the VK_* associated with keycode10 */
507 static WORD EVENT_event_to_vkey( XKeyEvent *e)
509 static int keysyms_per_keycode;
510 int i;
511 KeySym keysym;
513 if (!keysyms_per_keycode) /* First time : Initialization */
515 KeySym *ksp;
516 XModifierKeymap *mmp;
517 KeyCode *kcp;
518 XKeyEvent e2;
519 WORD vkey, OEMvkey;
521 XDisplayKeycodes(e->display, &min_keycode, &max_keycode);
522 ksp = XGetKeyboardMapping(e->display, min_keycode,
523 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
524 /* We are only interested in keysyms_per_keycode.
525 There is no need to hold a local copy of the keysyms table */
526 XFree(ksp);
527 mmp = XGetModifierMapping(e->display);
528 kcp = mmp->modifiermap;
529 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
531 int j;
533 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
534 if (*kcp)
536 int k;
538 for (k = 0; k < keysyms_per_keycode; k += 1)
539 if (XKeycodeToKeysym(e->display, *kcp, k)
540 == XK_Mode_switch)
542 AltGrMask = 1 << i;
543 dprintf_key(stddeb, "AltGrMask is %x\n", AltGrMask);
547 XFreeModifiermap(mmp);
549 /* Now build two conversion arrays :
550 * keycode -> vkey + extended
551 * vkey + extended -> keycode */
553 e2.display = e->display;
554 e2.state = 0;
556 OEMvkey = 0xb9; /* first OEM virtual key available is ba */
557 for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
559 XLookupString(&e2, NULL, 0, &keysym, NULL);
560 vkey = 0;
561 if (keysym) /* otherwise, keycode not used */
563 if ((keysym >> 8) == 0xFF) /* non-character key */
565 int key = keysym & 0xff;
567 if (key >= 0x08 && key <= 0x1B) /* special key */
568 vkey = special_key[key - 0x08];
569 else if (key >= 0x50 && key <= 0x57) /* cursor key */
570 vkey = cursor_key[key - 0x50];
571 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
572 vkey = misc_key[key - 0x60];
573 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
574 vkey = keypad_key[key - 0x7E];
575 else if (key >= 0xBE && key <= 0xCD) /* function key */
577 vkey = function_key[key - 0xBE];
578 vkey |= 0x100; /* set extended bit */
580 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
581 vkey = modifier_key[key - 0xE1];
582 else if (key == 0xFF) /* DEL key */
583 vkey = VK_DELETE;
584 /* extended must also be set for ALT_R, CTRL_R,
585 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
586 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
587 switch (keysym)
589 case XK_Control_R :
590 case XK_Alt_R :
591 case XK_Insert :
592 case XK_Delete :
593 case XK_Home :
594 case XK_End :
595 case XK_Prior :
596 case XK_Next :
597 case XK_Left :
598 case XK_Up :
599 case XK_Right :
600 case XK_Down :
601 case XK_KP_Divide :
602 case XK_KP_Enter :
603 vkey |= 0x100;
606 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
608 keysym = XLookupKeysym(&e2, i);
609 if ((keysym >= VK_0 && keysym <= VK_9)
610 || (keysym >= VK_A && keysym <= VK_Z)
611 || keysym == VK_SPACE)
612 vkey = keysym;
615 if (!vkey)
617 /* Others keys: let's assign OEM virtual key codes in the allowed range,
618 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
619 switch (++OEMvkey)
621 case 0xc1 : OEMvkey=0xdb; break;
622 case 0xe5 : OEMvkey=0xe9; break;
623 case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
626 vkey = OEMvkey;
628 if (debugging_keyboard)
630 fprintf(stddeb,"OEM specific virtual key %X assigned to keycode %X :\n ("
631 ,OEMvkey,e2.keycode);
632 for (i = 0; i < keysyms_per_keycode; i += 1)
634 char *ksname;
636 keysym = XLookupKeysym(&e2, i);
637 ksname = XKeysymToString(keysym);
638 if (!ksname)
639 ksname = "NoSymbol";
640 fprintf(stddeb, "%lX (%s) ", keysym, ksname);
642 fprintf(stddeb, ")\n");
646 keyc2vkey[e2.keycode] = vkey;
647 } /* for */
648 } /* Initialization */
650 return keyc2vkey[e->keycode];
654 int EVENT_ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState,
655 LPVOID lpChar, WORD wFlags)
657 XKeyEvent e;
658 KeySym keysym;
659 static XComposeStatus cs;
660 int ret;
661 WORD keyc;
663 e.display = display;
664 e.keycode = 0;
665 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
666 { /* this could be speed up by making another table, an array of struct vkey,keycode
667 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
668 if ((keyc2vkey[keyc] & 0xFF)== wVirtKey) /* no need to make a more precise test (with the extended bit correctly set above wVirtKey ... VK* are different enough... */
670 if ((e.keycode) && ((wVirtKey<0x10) || (wVirtKey>0x12)))
671 /* it's normal to have 2 shift, control, and alt ! */
672 dprintf_keyboard(stddeb,"Strange ... the keycodes %X and %X are matching!\n",
673 e.keycode,keyc);
674 e.keycode = keyc;
677 if (!e.keycode)
679 fprintf(stderr,"Unknown virtual key %X !!! \n",wVirtKey);
680 return wVirtKey; /* whatever */
682 e.state = 0;
683 if (lpKeyState[VK_SHIFT] & 0x80)
684 e.state |= ShiftMask;
685 if (lpKeyState[VK_CAPITAL] & 0x80)
686 e.state |= LockMask;
687 if (lpKeyState[VK_CONTROL] & 0x80)
688 if (lpKeyState[VK_MENU] & 0x80)
689 e.state |= AltGrMask;
690 else
691 e.state |= ControlMask;
692 if (lpKeyState[VK_NUMLOCK] & 0x80)
693 e.state |= Mod2Mask;
694 dprintf_key(stddeb, "EVENT_ToAscii(%04X, %04X) : faked state = %X\n",
695 wVirtKey, wScanCode, e.state);
696 ret = XLookupString(&e, lpChar, 2, &keysym, &cs);
697 if (ret == 0)
699 BYTE dead_char = 0;
701 ((char*)lpChar)[1] = '\0';
702 switch (keysym)
704 case XK_dead_tilde :
705 case 0x1000FE7E : /* Xfree's XK_Dtilde */
706 dead_char = '~';
707 break;
708 case XK_dead_acute :
709 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
710 dead_char = 0xb4;
711 break;
712 case XK_dead_circumflex :
713 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
714 dead_char = '^';
715 break;
716 case XK_dead_grave :
717 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
718 dead_char = '`';
719 break;
720 case XK_dead_diaeresis :
721 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
722 dead_char = 0xa8;
723 break;
725 if (dead_char)
727 *(char*)lpChar = dead_char;
728 ret = -1;
730 else
732 char *ksname;
734 ksname = XKeysymToString(keysym);
735 if (!ksname)
736 ksname = "No Name";
737 if ((keysym >> 8) != 0xff)
739 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
740 keysym, ksname);
741 fprintf(stderr, " wVirtKey = %X, wScanCode = %X, keycode = %X, state = %X\n",
742 wVirtKey, wScanCode, e.keycode, e.state);
746 dprintf_key(stddeb, "EVENT_ToAscii about to return %d with char %x\n",
747 ret, *(char*)lpChar);
748 return ret;
751 typedef union
753 struct
755 unsigned long count : 16;
756 unsigned long code : 8;
757 unsigned long extended : 1;
758 unsigned long unused : 2;
759 unsigned long win_internal : 2;
760 unsigned long context : 1;
761 unsigned long previous : 1;
762 unsigned long transition : 1;
763 } lp1;
764 unsigned long lp2;
765 } KEYLP;
767 static void EVENT_key( XKeyEvent *event )
769 char Str[24];
770 XComposeStatus cs;
771 KeySym keysym;
772 WORD vkey = 0;
773 KEYLP keylp;
774 WORD message;
775 static BOOL force_extended = FALSE; /* hack for AltGr translation */
777 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
779 dprintf_key(stddeb, "EVENT_key : state = %X\n", event->state);
780 if (keysym == XK_Mode_switch)
782 dprintf_key(stddeb, "Alt Gr key event received\n");
783 event->keycode = XKeysymToKeycode(event->display, XK_Control_L);
784 dprintf_key(stddeb, "Control_L is keycode 0x%x\n", event->keycode);
785 EVENT_key(event);
786 event->keycode = XKeysymToKeycode(event->display, XK_Alt_L);
787 dprintf_key(stddeb, "Alt_L is keycode 0x%x\n", event->keycode);
788 force_extended = TRUE;
789 EVENT_key(event);
790 force_extended = FALSE;
791 return;
794 Str[ascii_chars] = '\0';
795 if (debugging_key)
797 char *ksname;
799 ksname = XKeysymToString(keysym);
800 if (!ksname)
801 ksname = "No Name";
802 fprintf(stddeb, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
803 event_names[event->type], keysym, ksname,
804 ascii_chars, Str[0] & 0xff, Str);
807 #if 0
808 /* Ctrl-Alt-Return enters the debugger */
809 if ((keysym == XK_Return) && (event->type == KeyPress) &&
810 (event->state & ControlMask) && (event->state & Mod1Mask))
811 DEBUG_EnterDebugger();
812 #endif
814 vkey = EVENT_event_to_vkey(event);
815 if (force_extended) vkey |= 0x100;
817 dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
818 event->keycode, vkey);
820 keylp.lp1.count = 1;
821 keylp.lp1.code = LOBYTE(event->keycode) - 8;
822 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
823 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
824 * don't remember where I read it - AK */
825 /* it's '1' under windows, when a dialog box appears
826 * and you press one of the underlined keys - DF*/
827 vkey &= 0xff;
828 if (event->type == KeyPress)
830 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
831 if (!(InputKeyStateTable[vkey] & 0x80))
832 InputKeyStateTable[vkey] ^= 0x01;
833 InputKeyStateTable[vkey] |= 0x80;
834 keylp.lp1.transition = 0;
835 message = (InputKeyStateTable[VK_MENU] & 0x80)
836 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
837 ? WM_SYSKEYDOWN : WM_KEYDOWN;
839 else
841 UINT sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
842 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
843 && (force_extended == FALSE); /* for Alt from AltGr */
845 InputKeyStateTable[vkey] &= ~0x80;
846 keylp.lp1.previous = 1;
847 keylp.lp1.transition = 1;
848 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
850 keylp.lp1.context = ( (event->state & Mod1Mask) ||
851 (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
852 dprintf_key(stddeb," wParam=%04X, lParam=%08lX\n",
853 vkey, keylp.lp2 );
854 dprintf_key(stddeb," InputKeyState=%X\n",
855 InputKeyStateTable[vkey]);
857 hardware_event( message, vkey, keylp.lp2, event->x_root - desktopX,
858 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0 );
862 /***********************************************************************
863 * EVENT_MotionNotify
865 static void EVENT_MotionNotify( XMotionEvent *event )
867 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
868 event->x_root - desktopX, event->y_root - desktopY,
869 event->time - MSG_WineStartTicks, 0 );
873 /***********************************************************************
874 * EVENT_DummyMotionNotify
876 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
878 void EVENT_DummyMotionNotify(void)
880 Window root, child;
881 int rootX, rootY, childX, childY;
882 unsigned int state;
884 if (XQueryPointer( display, rootWindow, &root, &child,
885 &rootX, &rootY, &childX, &childY, &state ))
887 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
888 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
893 /***********************************************************************
894 * EVENT_ButtonPress
896 static void EVENT_ButtonPress( XButtonEvent *event )
898 static WORD messages[NB_BUTTONS] =
899 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
900 int buttonNum = event->button - 1;
902 if (buttonNum >= NB_BUTTONS) return;
903 MouseButtonsStates[buttonNum] = 0x8000;
904 AsyncMouseButtonsStates[buttonNum] = 0x8000;
905 hardware_event( messages[buttonNum],
906 EVENT_XStateToKeyState( event->state ), 0L,
907 event->x_root - desktopX, event->y_root - desktopY,
908 event->time - MSG_WineStartTicks, 0 );
912 /***********************************************************************
913 * EVENT_ButtonRelease
915 static void EVENT_ButtonRelease( XButtonEvent *event )
917 static const WORD messages[NB_BUTTONS] =
918 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
919 int buttonNum = event->button - 1;
921 if (buttonNum >= NB_BUTTONS) return;
922 MouseButtonsStates[buttonNum] = FALSE;
923 hardware_event( messages[buttonNum],
924 EVENT_XStateToKeyState( event->state ), 0L,
925 event->x_root - desktopX, event->y_root - desktopY,
926 event->time - MSG_WineStartTicks, 0 );
930 /**********************************************************************
931 * EVENT_FocusIn
933 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
935 if (event->detail == NotifyPointer) return;
936 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
937 if ((hwnd != GetFocus32()) && !IsChild( hwnd, GetFocus32()))
938 SetFocus32( hwnd );
942 /**********************************************************************
943 * EVENT_FocusOut
945 * Note: only top-level override-redirect windows get FocusOut events.
947 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
949 if (event->detail == NotifyPointer) return;
950 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
951 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32()))
952 SetFocus32( 0 );
956 /**********************************************************************
957 * EVENT_ConfigureNotify
959 * The ConfigureNotify event is only selected on the desktop window
960 * and on top-level windows when the -managed flag is used.
962 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
964 /* FIXME: with -desktop xxx we get this event _before_ desktop
965 * window structure is created. WIN_GetDesktop() check is a hack.
968 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
970 desktopX = event->x;
971 desktopY = event->y;
973 else
975 WND *wndPtr;
976 WINDOWPOS16 *winpos;
977 RECT16 newWindowRect, newClientRect;
978 HRGN32 hrgnOldPos, hrgnNewPos;
980 if (!(wndPtr = WIN_FindWndPtr( hwnd )) ||
981 !(wndPtr->flags & WIN_MANAGED) )
982 return;
984 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
986 /* XTranslateCoordinates(display, event->window, rootWindow,
987 event->x, event->y, &event->x, &event->y, &child);
990 /* Fill WINDOWPOS struct */
991 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
992 winpos->hwnd = hwnd;
993 winpos->x = event->x;
994 winpos->y = event->y;
995 winpos->cx = event->width;
996 winpos->cy = event->height;
998 /* Check for unchanged attributes */
999 if(winpos->x == wndPtr->rectWindow.left &&
1000 winpos->y == wndPtr->rectWindow.top)
1001 winpos->flags |= SWP_NOMOVE;
1002 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
1003 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
1004 winpos->flags |= SWP_NOSIZE;
1006 /* Send WM_WINDOWPOSCHANGING */
1007 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
1009 /* Calculate new position and size */
1010 newWindowRect.left = event->x;
1011 newWindowRect.right = event->x + event->width;
1012 newWindowRect.top = event->y;
1013 newWindowRect.bottom = event->y + event->height;
1015 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
1016 &wndPtr->rectWindow, &wndPtr->rectClient,
1017 SEGPTR_GET(winpos), &newClientRect );
1019 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
1020 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
1021 CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
1023 /* Set new size and position */
1024 wndPtr->rectWindow = newWindowRect;
1025 wndPtr->rectClient = newClientRect;
1026 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
1027 SEGPTR_FREE(winpos);
1029 /* full window drag leaves unrepainted garbage without this */
1030 PAINT_RedrawWindow( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
1031 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW,
1032 RDW_C_USEHRGN );
1033 DeleteObject32(hrgnOldPos);
1034 DeleteObject32(hrgnNewPos);
1039 /***********************************************************************
1040 * EVENT_SelectionRequest
1042 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
1044 XSelectionEvent result;
1045 Atom rprop = None;
1046 Window request = event->requestor;
1048 if(event->target == XA_STRING)
1050 HANDLE16 hText;
1051 LPSTR text;
1052 int size,i,j;
1054 rprop = event->property;
1056 if(rprop == None) rprop = event->target;
1058 if(event->selection!=XA_PRIMARY) rprop = None;
1059 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
1060 else
1062 /* open to make sure that clipboard is available */
1064 BOOL couldOpen = OpenClipboard( pWnd->hwndSelf );
1065 char* lpstr = 0;
1067 hText = GetClipboardData(CF_TEXT);
1068 text = GlobalLock16(hText);
1069 size = GlobalSize16(hText);
1071 /* remove carriage returns */
1073 lpstr = (char*)xmalloc(size--);
1074 for(i=0,j=0; i < size && text[i]; i++ )
1076 if( text[i] == '\r' &&
1077 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1078 lpstr[j++] = text[i];
1080 lpstr[j]='\0';
1082 XChangeProperty(display, request, rprop,
1083 XA_STRING, 8, PropModeReplace,
1084 lpstr, j);
1085 free(lpstr);
1087 /* close only if we opened before */
1089 if(couldOpen) CloseClipboard();
1093 if(rprop==None)
1094 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
1096 result.type=SelectionNotify;
1097 result.display=display;
1098 result.requestor=request;
1099 result.selection=event->selection;
1100 result.property=rprop;
1101 result.target=event->target;
1102 result.time=event->time;
1103 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1107 /***********************************************************************
1108 * EVENT_SelectionNotify
1110 static void EVENT_SelectionNotify( XSelectionEvent *event )
1112 if (event->selection != XA_PRIMARY) return;
1114 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
1115 else CLIPBOARD_ReadSelection( event->requestor, event->property );
1117 dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
1121 /***********************************************************************
1122 * EVENT_SelectionClear
1124 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
1126 if (event->selection != XA_PRIMARY) return;
1127 CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf );
1131 /**********************************************************************
1132 * EVENT_ClientMessage
1134 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
1136 if (event->message_type != None && event->format == 32)
1138 if ((event->message_type == wmProtocols) &&
1139 (((Atom) event->data.l[0]) == wmDeleteWindow))
1140 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
1141 else if ( event->message_type == dndProtocol &&
1142 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
1144 unsigned long data_length;
1145 unsigned long aux_long;
1146 unsigned char* p_data = NULL;
1147 union {
1148 Atom atom_aux;
1149 POINT32 pt_aux;
1150 int i;
1151 } u;
1152 int x, y;
1153 BOOL16 bAccept;
1154 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
1155 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1156 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
1157 Window w_aux_root, w_aux_child;
1158 WND* pDropWnd;
1160 if( !lpDragInfo || !spDragInfo ) return;
1162 XQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child,
1163 &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
1165 lpDragInfo->hScope = pWnd->hwndSelf;
1166 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1168 /* find out drop point and drop window */
1169 if( x < 0 || y < 0 ||
1170 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1171 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1172 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1173 else
1175 bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
1176 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1178 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1179 GlobalFree16( hDragInfo );
1181 if( bAccept )
1183 XGetWindowProperty( display, DefaultRootWindow(display),
1184 dndSelection, 0, 65535, FALSE,
1185 AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
1186 &data_length, &aux_long, &p_data);
1188 if( !aux_long && p_data) /* don't bother if > 64K */
1190 char *p = (char*) p_data;
1191 char *p_drop;
1193 aux_long = 0;
1194 while( *p ) /* calculate buffer size */
1196 p_drop = p;
1197 if((u.i = *p) != -1 )
1198 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
1199 if( u.i == -1 ) *p = -1; /* mark as "bad" */
1200 else
1202 INT32 len = GetShortPathName32A( p, NULL, 0 );
1203 if (len) aux_long += len + 1;
1204 else *p = -1;
1206 p += strlen(p) + 1;
1208 if( aux_long && aux_long < 65535 )
1210 HDROP16 hDrop;
1211 LPDROPFILESTRUCT lpDrop;
1213 aux_long += sizeof(DROPFILESTRUCT) + 1;
1214 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
1215 lpDrop = (LPDROPFILESTRUCT) GlobalLock16( hDrop );
1217 if( lpDrop )
1219 lpDrop->wSize = sizeof(DROPFILESTRUCT);
1220 lpDrop->ptMousePos.x = (INT16)x;
1221 lpDrop->ptMousePos.y = (INT16)y;
1222 lpDrop->fInNonClientArea = (BOOL16)
1223 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1224 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1225 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1226 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1227 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
1228 p = p_data;
1229 while(*p)
1231 if( *p != -1 ) /* use only "good" entries */
1233 GetShortPathName32A( p, p_drop, 65535 );
1234 p_drop += strlen( p_drop ) + 1;
1236 p += strlen(p) + 1;
1238 *p_drop = '\0';
1239 PostMessage( pWnd->hwndSelf, WM_DROPFILES, (WPARAM16)hDrop, 0L );
1243 if( p_data ) XFree(p_data);
1245 } /* WS_EX_ACCEPTFILES */
1246 } /* dndProtocol */
1247 else
1248 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
1252 /**********************************************************************
1253 * EVENT_EnterNotify
1255 * Install colormap when Wine window is focused in
1256 * self-managed mode with private colormap
1259 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1261 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1262 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1263 XInstallColormap( display, COLOR_GetColormap() );
1267 /**********************************************************************
1268 * EVENT_MapNotify
1270 void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
1272 HWND32 hwndFocus = GetFocus32();
1274 if (hwndFocus && IsChild( hWnd, hwndFocus ))
1275 FOCUS_SetXFocus( (HWND32)hwndFocus );
1277 return;
1280 /**********************************************************************
1281 * EVENT_Capture
1283 * We need this to be able to generate double click messages
1284 * when menu code captures mouse in the window without CS_DBLCLK style.
1286 HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
1288 Window win;
1289 HWND32 old_capture_wnd = captureWnd;
1291 if (!hwnd)
1293 ReleaseCapture();
1294 return old_capture_wnd;
1296 if ((win = WIN_GetXWindow( hwnd )))
1298 if (XGrabPointer(display, win, False,
1299 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1300 GrabModeAsync, GrabModeAsync,
1301 None, None, CurrentTime ) == GrabSuccess)
1303 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
1304 captureWnd = hwnd;
1305 captureHT = ht;
1306 return old_capture_wnd;
1309 return 0;
1312 /**********************************************************************
1313 * EVENT_GetCaptureInfo
1315 INT16 EVENT_GetCaptureInfo()
1317 return captureHT;
1320 /**********************************************************************
1321 * SetCapture16 (USER.18)
1323 HWND16 SetCapture16( HWND16 hwnd )
1325 return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
1329 /**********************************************************************
1330 * SetCapture32 (USER32.463)
1332 HWND32 SetCapture32( HWND32 hwnd )
1334 return EVENT_Capture( hwnd, HTCLIENT );
1338 /**********************************************************************
1339 * ReleaseCapture (USER.19) (USER32.438)
1341 void ReleaseCapture(void)
1343 if (captureWnd == 0) return;
1344 XUngrabPointer( display, CurrentTime );
1345 captureWnd = 0;
1346 dprintf_win(stddeb, "ReleaseCapture\n");
1350 /**********************************************************************
1351 * GetCapture16 (USER.236)
1353 HWND16 GetCapture16(void)
1355 return (HWND16)captureWnd;
1359 /**********************************************************************
1360 * GetCapture32 (USER32.207)
1362 HWND32 GetCapture32(void)
1364 return captureWnd;
1368 /***********************************************************************
1369 * GetMouseEventProc (USER.337)
1371 FARPROC16 GetMouseEventProc(void)
1373 HMODULE16 hmodule = GetModuleHandle("USER");
1374 return MODULE_GetEntryPoint( hmodule,
1375 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
1379 /***********************************************************************
1380 * Mouse_Event (USER.299)
1382 void Mouse_Event( CONTEXT *context )
1384 /* Register values:
1385 * AX = mouse event
1386 * BX = horizontal displacement if AX & ME_MOVE
1387 * CX = vertical displacement if AX & ME_MOVE
1388 * DX = button state (?)
1389 * SI = mouse event flags (?)
1391 Window root, child;
1392 int rootX, rootY, childX, childY;
1393 unsigned int state;
1395 if (AX_reg(context) & ME_MOVE)
1397 /* We have to actually move the cursor */
1398 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
1399 (short)BX_reg(context), (short)CX_reg(context) );
1400 return;
1402 if (!XQueryPointer( display, rootWindow, &root, &child,
1403 &rootX, &rootY, &childX, &childY, &state )) return;
1404 if (AX_reg(context) & ME_LDOWN)
1405 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1406 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1407 if (AX_reg(context) & ME_LUP)
1408 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1409 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1410 if (AX_reg(context) & ME_RDOWN)
1411 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1412 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1413 if (AX_reg(context) & ME_RUP)
1414 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1415 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1419 /**********************************************************************
1420 * EnableHardwareInput (USER.331)
1422 BOOL16 EnableHardwareInput(BOOL16 bEnable)
1424 BOOL16 bOldState = InputEnabled;
1425 dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
1426 InputEnabled = bEnable;
1427 return bOldState;