Release 0.4.10
[wine] / windows / event.c
1 /*
2  * X events handling functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
11 #include <X11/Core.h>
12
13 #include "windows.h"
14 #include "win.h"
15 #include "class.h"
16
17
18 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
19 static WORD dblclick_time = 300; /* Max. time for a double click (milliseconds) */
20
21   /* Event handlers */
22 static void EVENT_expose();
23 static void EVENT_key();
24 static void EVENT_mouse_motion();
25 static void EVENT_mouse_button();
26 static void EVENT_structure();
27 static void EVENT_focus_change();
28
29   /* State variables */
30 static HWND captureWnd = 0;
31
32 extern HWND hWndFocus;
33
34 /***********************************************************************
35  *           EVENT_AddHandlers
36  *
37  * Add the event handlers to the given window
38  */
39 void EVENT_AddHandlers( Widget w, int hwnd )
40 {
41     XtAddEventHandler(w, ExposureMask, FALSE,
42                       EVENT_expose, (XtPointer)hwnd );
43     XtAddEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
44                       EVENT_key, (XtPointer)hwnd );
45     XtAddEventHandler(w, PointerMotionMask, FALSE,
46                       EVENT_mouse_motion, (XtPointer)hwnd );
47     XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
48                       EVENT_mouse_button, (XtPointer)hwnd );
49     XtAddEventHandler(w, StructureNotifyMask, FALSE,
50                       EVENT_structure, (XtPointer)hwnd );
51     XtAddEventHandler(w, FocusChangeMask, FALSE,
52                       EVENT_focus_change, (XtPointer)hwnd );
53 }
54
55
56 /***********************************************************************
57  *           EVENT_RemoveHandlers
58  *
59  * Remove the event handlers of the given window
60  */
61 void EVENT_RemoveHandlers( Widget w, int hwnd )
62 {
63     XtRemoveEventHandler(w, ExposureMask, FALSE,
64                          EVENT_expose, (XtPointer)hwnd );
65     XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
66                          EVENT_key, (XtPointer)hwnd );
67     XtRemoveEventHandler(w, PointerMotionMask, FALSE,
68                          EVENT_mouse_motion, (XtPointer)hwnd );
69     XtRemoveEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
70                          EVENT_mouse_button, (XtPointer)hwnd );
71     XtRemoveEventHandler(w, StructureNotifyMask, FALSE,
72                          EVENT_structure, (XtPointer)hwnd );
73     XtRemoveEventHandler(w, FocusChangeMask, FALSE,
74                          EVENT_focus_change, (XtPointer)hwnd );
75 }
76
77
78 /***********************************************************************
79  *           EVENT_XStateToKeyState
80  *
81  * Translate a X event state (Button1Mask, ShiftMask, etc...) to
82  * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
83  */
84 static WORD EVENT_XStateToKeyState( int state )
85 {
86     int kstate = 0;
87     
88     if (state & Button1Mask) kstate |= MK_LBUTTON;
89     if (state & Button2Mask) kstate |= MK_MBUTTON;
90     if (state & Button3Mask) kstate |= MK_RBUTTON;
91     if (state & ShiftMask)   kstate |= MK_SHIFT;
92     if (state & ControlMask) kstate |= MK_CONTROL;
93     return kstate;
94 }
95
96
97 /***********************************************************************
98  *           EVENT_expose
99  *
100  * Handle a X expose event
101  */
102 static void EVENT_expose( Widget w, int hwnd, XExposeEvent *event,
103                           Boolean *cont_dispatch )
104 {
105     RECT rect;
106     rect.left   = event->x;
107     rect.top    = event->y;
108     rect.right  = event->x + event->width;
109     rect.bottom = event->y + event->height;
110     
111     InvalidateRect( hwnd, &rect, TRUE );
112 }
113
114
115 /***********************************************************************
116  *           EVENT_key
117  *
118  * Handle a X key event
119  */
120 static void EVENT_key( Widget w, int hwnd, XKeyEvent *event,
121                        Boolean *cont_dispatch )
122 {
123     MSG msg;
124
125     char Str[24]; 
126     XComposeStatus cs; 
127     KeySym key;
128     int count = XLookupString(event, Str, 1, &key, &cs);
129     Str[count] = '\0';
130 #ifdef DEBUG_KEY
131     printf("WM_KEY??? : count=%u / %X / '%s'\n",count, Str[0], Str);
132 #endif    
133     msg.hwnd    = hwnd;
134     msg.message = (event->type == KeyRelease) ? WM_KEYUP : WM_KEYDOWN;
135     msg.wParam  = Str[0];
136     msg.lParam  = (event->x & 0xffff) | (event->y << 16);
137     msg.time = event->time;
138     msg.pt.x = event->x & 0xffff;
139     msg.pt.y = event->y & 0xffff;
140     
141     MSG_AddMsg( &msg );    
142 }
143
144
145 /***********************************************************************
146  *           EVENT_mouse_motion
147  *
148  * Handle a X mouse motion event
149  */
150 static void EVENT_mouse_motion( Widget w, int hwnd, XMotionEvent *event, 
151                                 Boolean *cont_dispatch )
152 {
153     MSG msg;
154     
155     msg.hwnd    = hwnd;
156     msg.message = WM_MOUSEMOVE;
157     msg.wParam  = EVENT_XStateToKeyState( event->state );
158     msg.lParam  = (event->x & 0xffff) | (event->y << 16);
159     msg.time = event->time;
160     msg.pt.x = event->x & 0xffff;
161     msg.pt.y = event->y & 0xffff;
162     
163     MSG_AddMsg( &msg );    
164 }
165
166
167 /***********************************************************************
168  *           EVENT_mouse_button
169  *
170  * Handle a X mouse button event
171  */
172 static void EVENT_mouse_button( Widget w, int hwnd, XButtonEvent *event,
173                                 Boolean *cont_dispatch )
174 {
175     static WORD messages[3][NB_BUTTONS] = 
176     {
177         { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN },
178         { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP },
179         { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK }
180     };
181     static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
182         
183     MSG msg;
184     int buttonNum, prevTime, type;
185     
186     buttonNum = event->button-1;
187     if (buttonNum >= NB_BUTTONS) return;
188     if (event->type == ButtonRelease) type = 1;
189     else
190     {  /* Check if double-click */
191         prevTime = lastClickTime[buttonNum];
192         lastClickTime[buttonNum] = event->time;
193         if (event->time - prevTime < dblclick_time)
194         {
195             WND * wndPtr;
196             CLASS * classPtr;
197             if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
198             if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return;
199             type = (classPtr->wc.style & CS_DBLCLKS) ? 2 : 0;
200         }
201         else type = 0;
202     }   
203     
204     msg.hwnd    = hwnd;
205     msg.message = messages[type][buttonNum];
206     msg.wParam  = EVENT_XStateToKeyState( event->state );
207     msg.lParam  = (event->x & 0xffff) | (event->y << 16);
208     msg.time = event->time;
209     msg.pt.x = event->x & 0xffff;
210     msg.pt.y = event->y & 0xffff;
211
212     MSG_AddMsg( &msg );    
213 }
214
215
216 /***********************************************************************
217  *           EVENT_structure
218  *
219  * Handle a X StructureNotify event
220  */
221 static void EVENT_structure( Widget w, int hwnd, XEvent *event, 
222                              Boolean *cont_dispatch )
223 {
224     MSG msg;
225     
226     msg.hwnd = hwnd;
227     msg.time = GetTickCount();
228     msg.pt.x = 0;
229     msg.pt.y = 0;
230
231     switch(event->type)
232     {
233       case ConfigureNotify:
234         {
235             XConfigureEvent * evt = (XConfigureEvent *)event;
236             WND * wndPtr = WIN_FindWndPtr( hwnd );
237             if (!wndPtr) return;
238             wndPtr->rectClient.right  = wndPtr->rectClient.left + evt->width;
239             wndPtr->rectClient.bottom = wndPtr->rectClient.top + evt->height;
240             PostMessage( hwnd, WM_SIZE, SIZE_RESTORED,
241                          (evt->width & 0xffff) | (evt->height << 16) );
242         }
243         break;
244         
245     }    
246 }
247
248
249 /**********************************************************************
250  *              EVENT_focus_change
251  *
252  * Handle an X FocusChange event
253  */
254 static void EVENT_focus_change( Widget w, int hwnd, XEvent *event, 
255                                Boolean *cont_dispatch )
256 {
257     MSG msg;
258     
259     msg.hwnd = hwnd;
260     msg.time = GetTickCount();
261     msg.pt.x = 0;
262     msg.pt.y = 0;
263
264     switch(event->type)
265     {
266       case FocusIn:
267         {
268             msg.message = WM_SETFOCUS;
269             msg.wParam = hwnd;
270             hWndFocus = hwnd;
271
272         }
273         break;
274         
275       case FocusOut:
276         {
277             if (hWndFocus)
278             {
279                 msg.message = WM_KILLFOCUS;
280                 msg.wParam = hwnd;
281                 hWndFocus = 0;
282             }
283         }
284     }    
285     MSG_AddMsg( &msg );
286 }
287
288
289 /**********************************************************************
290  *              SetCapture      (USER.18)
291  */
292 HWND SetCapture(HWND wnd)
293 {
294     int rv;
295     HWND old_capture_wnd = captureWnd;
296     WND *wnd_p = WIN_FindWndPtr(wnd);
297     if (wnd_p == NULL)
298         return 0;
299     
300     rv = XtGrabPointer(wnd_p->winWidget, False, 
301                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
302                        GrabModeAsync, GrabModeSync, None, None, CurrentTime);
303
304     if (rv == GrabSuccess)
305     {
306         captureWnd = wnd;
307         return old_capture_wnd;
308     }
309     else
310         return 0;
311 }
312
313 /**********************************************************************
314  *              ReleaseCapture  (USER.19)
315  */
316 void ReleaseCapture()
317 {
318     WND *wnd_p;
319     
320     if (captureWnd == 0)
321         return;
322     
323     wnd_p = WIN_FindWndPtr(captureWnd);
324     if (wnd_p == NULL)
325         return;
326     
327     XtUngrabPointer(wnd_p->winWidget, CurrentTime);
328
329     captureWnd = 0;
330 }
331
332 /**********************************************************************
333  *              SetDoubleClickTime  (USER.20)
334  */
335 void SetDoubleClickTime (WORD interval)
336 {
337         if (interval == 0)
338                 dblclick_time = 500;
339         else
340                 dblclick_time = interval;
341 }               
342
343 /**********************************************************************
344  *              GetDoubleClickTime  (USER.21)
345  */
346 WORD GetDoubleClickTime ()
347 {
348         return ((WORD)dblclick_time);
349 }               
350
351