2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
20 /* #define DEBUG_EVENT /* */
21 /* #undef DEBUG_EVENT /* */
22 /* #define DEBUG_KEY /* */
23 /* #undef DEBUG_KEY /* */
29 typedef char *XPointer
;
34 /* Dirty hack to compile with Sun's OpenWindows */
35 typedef char *XPointer
;
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;
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 */
66 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
67 VK_NEXT
, VK_END
/* FF50 */
72 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
73 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
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
,
102 0, VK_MENU
, VK_MENU
/* FFE8 */
109 unsigned long count
: 16;
110 unsigned long code
: 8;
111 unsigned long extended
: 1;
113 unsigned long context
: 1;
114 unsigned long previous
: 1;
115 unsigned long transition
: 1;
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"
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 /***********************************************************************
148 * Process an X event.
150 void EVENT_ProcessEvent( XEvent
*event
)
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
);
165 EVENT_key( (XKeyEvent
*)event
);
169 EVENT_ButtonPress( (XButtonEvent
*)event
);
173 EVENT_ButtonRelease( (XButtonEvent
*)event
);
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
);
191 EVENT_FocusOut( hwnd
, (XFocusChangeEvent
*)event
);
195 EVENT_Expose( hwnd
, (XExposeEvent
*)event
);
198 case ConfigureNotify
:
199 EVENT_ConfigureNotify( hwnd
, (XConfigureEvent
*)event
);
203 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %d\n",
204 event_names
[event
->type
], hwnd
);
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
)
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
;
241 /***********************************************************************
244 static void EVENT_Expose( HWND hwnd
, XExposeEvent
*event
)
248 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
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 /***********************************************************************
267 * Handle a X key event
269 static void EVENT_key( XKeyEvent
*event
)
274 WORD xkey
, vkey
, key_type
, key
;
276 BOOL extended
= FALSE
;
278 int count
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
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
);
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];
301 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
303 vkey
= function_key
[key
- 0xBE];
306 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
307 vkey
= modifier_key
[key
- 0xE1];
308 else if (key
== 0xFF) /* DEL key */
311 else if (key_type
== 0) /* character key */
313 if (key
>= 0x61 && key
<= 0x7A)
314 vkey
= key
- 0x20; /* convert lower to uppercase */
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;
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",
333 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
334 hardware_event( ALTKeyState
? WM_SYSKEYDOWN
: WM_KEYDOWN
,
336 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
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
);
353 if (vkey
== VK_MENU
) ALTKeyState
= FALSE
;
354 KeyStateTable
[vkey
] &= 0xf0;
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",
363 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
364 hardware_event( ((ALTKeyState
|| vkey
== VK_MENU
) ?
365 WM_SYSKEYUP
: WM_KEYUP
),
367 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
374 /***********************************************************************
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
,
385 /***********************************************************************
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
,
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
,
422 /**********************************************************************
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
)
447 /**********************************************************************
448 * SetCapture (USER.18)
450 HWND
SetCapture( HWND hwnd
)
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
)
462 return old_capture_wnd
;
468 /**********************************************************************
469 * ReleaseCapture (USER.19)
471 void ReleaseCapture()
473 if (captureWnd
== 0) return;
474 XUngrabPointer( display
, CurrentTime
);
478 /**********************************************************************
479 * GetCapture (USER.236)
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
);