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
;
121 static const char *event_names
[] =
123 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
124 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
125 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
126 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
127 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
128 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
129 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
130 "ClientMessage", "MappingNotify"
134 static void EVENT_key( XKeyEvent
*event
);
135 static void EVENT_ButtonPress( XButtonEvent
*event
);
136 static void EVENT_ButtonRelease( XButtonEvent
*event
);
137 static void EVENT_MotionNotify( XMotionEvent
*event
);
138 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
);
139 static void EVENT_Expose( HWND hwnd
, XExposeEvent
*event
);
140 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
141 static void EVENT_SelectionRequest( HWND hwnd
, XSelectionRequestEvent
*event
);
142 static void EVENT_SelectionNotify( HWND hwnd
, XSelectionEvent
*event
);
143 static void EVENT_SelectionClear( HWND hwnd
, XSelectionClearEvent
*event
);
146 /***********************************************************************
149 * Process an X event.
151 void EVENT_ProcessEvent( XEvent
*event
)
156 XFindContext( display
, ((XAnyEvent
*)event
)->window
, winContext
, &ptr
);
157 hwnd
= (HWND
) (int)ptr
;
159 dprintf_event(stddeb
, "Got event %s for hwnd "NPFMT
"\n",
160 event_names
[event
->type
], hwnd
);
166 EVENT_key( (XKeyEvent
*)event
);
170 EVENT_ButtonPress( (XButtonEvent
*)event
);
174 EVENT_ButtonRelease( (XButtonEvent
*)event
);
178 /* Wine between two fast machines across the overloaded campus
179 ethernet gets very boged down in MotionEvents. The following
180 simply finds the last motion event in the queue and drops
181 the rest. On a good link events are servered before they build
182 up so this doesn't take place. On a slow link this may cause
183 problems if the event order is important. I'm not yet seen
184 of any problems. Jon 7/6/96.
186 while (XCheckTypedWindowEvent(display
, ((XAnyEvent
*)event
)->window
,
187 MotionNotify
, event
));
188 EVENT_MotionNotify( (XMotionEvent
*)event
);
192 EVENT_FocusOut( hwnd
, (XFocusChangeEvent
*)event
);
196 EVENT_Expose( hwnd
, (XExposeEvent
*)event
);
199 case ConfigureNotify
:
200 EVENT_ConfigureNotify( hwnd
, (XConfigureEvent
*)event
);
203 case SelectionRequest
:
204 EVENT_SelectionRequest( hwnd
, (XSelectionRequestEvent
*)event
);
207 case SelectionNotify
:
208 EVENT_SelectionNotify( hwnd
, (XSelectionEvent
*)event
);
212 EVENT_SelectionClear( hwnd
, (XSelectionClearEvent
*) event
);
216 dprintf_event(stddeb
, "Unprocessed event %s for hwnd "NPFMT
"\n",
217 event_names
[event
->type
], hwnd
);
223 /***********************************************************************
224 * EVENT_RegisterWindow
226 * Associate an X window to a HWND.
228 void EVENT_RegisterWindow( Window w
, HWND hwnd
)
230 if (!winContext
) winContext
= XUniqueContext();
231 XSaveContext( display
, w
, winContext
, (XPointer
)(int)hwnd
);
235 /***********************************************************************
236 * EVENT_XStateToKeyState
238 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
239 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
241 static WORD
EVENT_XStateToKeyState( int state
)
245 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
246 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
247 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
248 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
249 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
254 /***********************************************************************
257 static void EVENT_Expose( HWND hwnd
, XExposeEvent
*event
)
260 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
263 /* Make position relative to client area instead of window */
264 rect
.left
= event
->x
- (wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
);
265 rect
.top
= event
->y
- (wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
);
266 rect
.right
= rect
.left
+ event
->width
;
267 rect
.bottom
= rect
.top
+ event
->height
;
269 RedrawWindow( hwnd
, &rect
, 0,
270 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
271 (event
->count
? 0 : RDW_ERASENOW
) );
275 /***********************************************************************
278 * Handle a X key event
280 static void EVENT_key( XKeyEvent
*event
)
286 WORD xkey
, key_type
, key
;
288 BOOL extended
= FALSE
;
290 int count
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
292 dprintf_key(stddeb
,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
293 keysym
, count
, Str
[0], Str
);
295 xkey
= LOWORD(keysym
);
296 key_type
= HIBYTE(xkey
);
298 dprintf_key(stddeb
," key_type=%X, key=%X\n", key_type
, key
);
300 if (key_type
== 0xFF) /* non-character key */
302 if (key
>= 0x08 && key
<= 0x1B) /* special key */
303 vkey
= special_key
[key
- 0x08];
304 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
305 vkey
= cursor_key
[key
- 0x50];
306 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
307 vkey
= misc_key
[key
- 0x60];
308 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
310 vkey
= keypad_key
[key
- 0x7E];
313 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
315 vkey
= function_key
[key
- 0xBE];
318 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
319 vkey
= modifier_key
[key
- 0xE1];
320 else if (key
== 0xFF) /* DEL key */
323 else if (key_type
== 0) /* character key */
326 vkey
= toupper(key
); /* convert lower to uppercase */
331 if (event
->type
== KeyPress
)
333 if (vkey
== VK_MENU
) ALTKeyState
= TRUE
;
334 if (!(KeyStateTable
[vkey
] & 0x0f))
335 KeyStateTable
[vkey
] ^= 0x80;
336 KeyStateTable
[vkey
] |= 0x01;
338 keylp
.lp1
.code
= LOBYTE(event
->keycode
);
339 keylp
.lp1
.extended
= (extended
? 1 : 0);
340 keylp
.lp1
.context
= (event
->state
& Mod1Mask
? 1 : 0);
341 keylp
.lp1
.previous
= (KeyDown
? 0 : 1);
342 keylp
.lp1
.transition
= 0;
343 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
345 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
346 hardware_event( ALTKeyState
? WM_SYSKEYDOWN
: WM_KEYDOWN
,
348 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
352 /* The key translation ought to take place in TranslateMessage().
353 * However, there is no way of passing the required information
354 * in a Windows message, so TranslateMessage does not currently
355 * do anything and the translation is done here.
357 if (count
== 1) /* key has an ASCII representation */
359 dprintf_key(stddeb
,"WM_CHAR : wParam=%X\n", (WORD
)Str
[0] );
360 PostMessage( GetFocus(), WM_CHAR
, (WORD
)(unsigned char)(Str
[0]),
366 if (vkey
== VK_MENU
) ALTKeyState
= FALSE
;
367 KeyStateTable
[vkey
] &= 0xf0;
369 keylp
.lp1
.code
= LOBYTE(event
->keycode
);
370 keylp
.lp1
.extended
= (extended
? 1 : 0);
371 keylp
.lp1
.context
= (event
->state
& Mod1Mask
? 1 : 0);
372 keylp
.lp1
.previous
= 1;
373 keylp
.lp1
.transition
= 1;
374 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
376 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
377 hardware_event( ((ALTKeyState
|| vkey
== VK_MENU
) ?
378 WM_SYSKEYUP
: WM_KEYUP
),
380 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
387 /***********************************************************************
390 static void EVENT_MotionNotify( XMotionEvent
*event
)
392 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
393 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
398 /***********************************************************************
399 * EVENT_DummyMotionNotify
401 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
403 void EVENT_DummyMotionNotify(void)
406 int rootX
, rootY
, childX
, childY
;
409 if (XQueryPointer( display
, rootWindow
, &root
, &child
,
410 &rootX
, &rootY
, &childX
, &childY
, &state
))
412 hardware_event(WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
413 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0 );
418 /***********************************************************************
421 static void EVENT_ButtonPress( XButtonEvent
*event
)
423 static WORD messages
[NB_BUTTONS
] =
424 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
425 int buttonNum
= event
->button
- 1;
427 if (buttonNum
>= NB_BUTTONS
) return;
428 MouseButtonsStates
[buttonNum
] = TRUE
;
429 AsyncMouseButtonsStates
[buttonNum
] = TRUE
;
430 hardware_event( messages
[buttonNum
],
431 EVENT_XStateToKeyState( event
->state
), 0L,
432 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
437 /***********************************************************************
438 * EVENT_ButtonRelease
440 static void EVENT_ButtonRelease( XButtonEvent
*event
)
442 static const WORD messages
[NB_BUTTONS
] =
443 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
444 int buttonNum
= event
->button
- 1;
446 if (buttonNum
>= NB_BUTTONS
) return;
447 MouseButtonsStates
[buttonNum
] = FALSE
;
448 hardware_event( messages
[buttonNum
],
449 EVENT_XStateToKeyState( event
->state
), 0L,
450 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
455 /**********************************************************************
458 * Note: only top-level override-redirect windows get FocusOut events.
460 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
)
462 if (event
->detail
== NotifyPointer
) return;
463 if (hwnd
== GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE
);
464 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus())) SetFocus( 0 );
468 /**********************************************************************
469 * EVENT_ConfigureNotify
471 * The ConfigureNotify event is only selected on the desktop window.
473 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
)
480 /***********************************************************************
481 * EVENT_SelectionRequest
483 static void EVENT_SelectionRequest( HWND hwnd
, XSelectionRequestEvent
*event
)
485 XSelectionEvent result
;
487 Window request
=event
->requestor
;
489 if(event
->target
== XA_STRING
)
493 rprop
=event
->property
;
494 if(rprop
== None
)rprop
=event
->target
;
495 if(event
->selection
!=XA_PRIMARY
)rprop
=None
;
496 else if(!IsClipboardFormatAvailable(CF_TEXT
))rprop
=None
;
498 /* Don't worry if we can't open */
499 BOOL couldOpen
=OpenClipboard(hwnd
);
500 hText
=GetClipboardData(CF_TEXT
);
501 text
=GlobalLock(hText
);
502 XChangeProperty(display
,request
,rprop
,XA_STRING
,
503 8,PropModeReplace
,text
,strlen(text
));
505 /* close only if we opened before */
506 if(couldOpen
)CloseClipboard();
509 if(rprop
==None
) dprintf_event(stddeb
,"Request for %s ignored\n",
510 XGetAtomName(display
,event
->target
));
511 result
.type
=SelectionNotify
;
512 result
.display
=display
;
513 result
.requestor
=request
;
514 result
.selection
=event
->selection
;
515 result
.property
=rprop
;
516 result
.target
=event
->target
;
517 result
.time
=event
->time
;
518 XSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
522 /***********************************************************************
523 * EVENT_SelectionNotify
525 static void EVENT_SelectionNotify(HWND hwnd
, XSelectionEvent
*event
)
527 if(event
->selection
!=XA_PRIMARY
)return;
528 if(event
->target
!=XA_STRING
)CLIPBOARD_ReadSelection(0,None
);
529 CLIPBOARD_ReadSelection(event
->requestor
,event
->property
);
533 /***********************************************************************
534 * EVENT_SelectionClear
536 static void EVENT_SelectionClear(HWND hwnd
, XSelectionClearEvent
*event
)
538 if(event
->selection
!=XA_PRIMARY
)return;
539 CLIPBOARD_ReleaseSelection(hwnd
);
542 /**********************************************************************
543 * SetCapture (USER.18)
545 HWND
SetCapture( HWND hwnd
)
548 HWND old_capture_wnd
= captureWnd
;
553 return old_capture_wnd
;
555 if (!(win
= WIN_GetXWindow( hwnd
))) return 0;
556 if (XGrabPointer(display
, win
, False
,
557 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
558 GrabModeAsync
, GrabModeAsync
,
559 None
, None
, CurrentTime
) == GrabSuccess
)
561 dprintf_win(stddeb
, "SetCapture: "NPFMT
"\n", hwnd
);
563 return old_capture_wnd
;
569 /**********************************************************************
570 * ReleaseCapture (USER.19)
572 void ReleaseCapture()
574 if (captureWnd
== 0) return;
575 XUngrabPointer( display
, CurrentTime
);
577 dprintf_win(stddeb
, "ReleaseCapture\n");
580 /**********************************************************************
581 * GetCapture (USER.236)
589 /**********************************************************************
590 * EnableHardwareInput [USER.331]
592 BOOL
EnableHardwareInput(BOOL bEnable
)
594 BOOL bOldState
= InputEnabled
;
595 dprintf_event(stdnimp
,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable
);
596 InputEnabled
= bEnable
;
597 return (bOldState
&& !bEnable
);