2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
12 #include <X11/Xresource.h>
13 #include <X11/Xutil.h>
14 #include <X11/Xatom.h>
20 #include "clipboard.h"
23 /* #define DEBUG_EVENT */
24 /* #define DEBUG_KEY */
30 typedef char *XPointer
;
34 #ifdef WHO_NEEDS_DIRTY_HACKS
36 /* Dirty hack to compile with Sun's OpenWindows */
37 typedef char *XPointer
;
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;
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 */
65 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
66 VK_NEXT
, VK_END
/* FF50 */
71 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
72 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
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
,
101 0, VK_MENU
, VK_MENU
/* FFE8 */
108 unsigned long count
: 16;
109 unsigned long code
: 8;
110 unsigned long extended
: 1;
112 unsigned long context
: 1;
113 unsigned long previous
: 1;
114 unsigned long transition
: 1;
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"
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 /***********************************************************************
150 * Process an X event.
152 void EVENT_ProcessEvent( XEvent
*event
)
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
);
167 EVENT_key( (XKeyEvent
*)event
);
171 EVENT_ButtonPress( (XButtonEvent
*)event
);
175 EVENT_ButtonRelease( (XButtonEvent
*)event
);
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
);
193 EVENT_FocusOut( hwnd
, (XFocusChangeEvent
*)event
);
197 EVENT_Expose( hwnd
, (XExposeEvent
*)event
);
200 case ConfigureNotify
:
201 EVENT_ConfigureNotify( hwnd
, (XConfigureEvent
*)event
);
204 case SelectionRequest
:
205 EVENT_SelectionRequest( hwnd
, (XSelectionRequestEvent
*)event
);
208 case SelectionNotify
:
209 EVENT_SelectionNotify( hwnd
, (XSelectionEvent
*)event
);
213 EVENT_SelectionClear( hwnd
, (XSelectionClearEvent
*) event
);
217 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %d\n",
218 event_names
[event
->type
], hwnd
);
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
)
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
;
255 /***********************************************************************
258 static void EVENT_Expose( HWND hwnd
, XExposeEvent
*event
)
261 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
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 /***********************************************************************
279 * Handle a X key event
281 static void EVENT_key( XKeyEvent
*event
)
287 WORD xkey
, key_type
, key
;
289 BOOL extended
= FALSE
;
291 int count
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
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
);
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];
314 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
316 vkey
= function_key
[key
- 0xBE];
319 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
320 vkey
= modifier_key
[key
- 0xE1];
321 else if (key
== 0xFF) /* DEL key */
324 else if (key_type
== 0) /* character key */
327 vkey
= toupper(key
); /* convert lower to uppercase */
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;
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",
346 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
347 hardware_event( ALTKeyState
? WM_SYSKEYDOWN
: WM_KEYDOWN
,
349 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
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]),
367 if (vkey
== VK_MENU
) ALTKeyState
= FALSE
;
368 KeyStateTable
[vkey
] &= 0xf0;
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",
377 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
378 hardware_event( ((ALTKeyState
|| vkey
== VK_MENU
) ?
379 WM_SYSKEYUP
: WM_KEYUP
),
381 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
388 /***********************************************************************
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
,
399 /***********************************************************************
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
,
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
,
436 /**********************************************************************
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
)
461 /***********************************************************************
462 * EVENT_SelectionRequest
464 static void EVENT_SelectionRequest( HWND hwnd
, XSelectionRequestEvent
*event
)
466 XSelectionEvent result
;
468 Window request
=event
->requestor
;
470 if(event
->target
== XA_STRING
)
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
;
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
));
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
)
529 HWND old_capture_wnd
= captureWnd
;
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
);
544 return old_capture_wnd
;
550 /**********************************************************************
551 * ReleaseCapture (USER.19)
553 void ReleaseCapture()
555 if (captureWnd
== 0) return;
556 XUngrabPointer( display
, CurrentTime
);
558 dprintf_win(stddeb
, "ReleaseCapture\n");
561 /**********************************************************************
562 * GetCapture (USER.236)
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
);