Rune - Stabilization
[rune.git] / ext_x11 / dll / xevent.c
1 /*
2  * XEVENT.C     - Handle X events for our display
3  *
4  * Obtains the next X event, blocking if necessary, and allocates and
5  * returns a Frame.Event structure.
6  */
7
8 #include "defs.h"
9
10 rundata_t
11 run_XEvent(runctx_p ct, Exp *exp)
12 {
13         RunTmpStor *ts = InterpGetExpTmpData(ct, exp);
14         XEvent xevent;
15         static XEvent xsave;
16         Event *event;
17         int state = 0;
18         rundata_t data;
19
20         dassert(EventType.ty_Bytes == sizeof(Event));
21
22         for (;;) {
23                 int aggMode = 1;
24
25                 /*
26                  * Wait for the next event.   If no events remain and we
27                  * have a saved event pending, use the saved event.
28                  * Otherwise block and loop.
29                  */
30                 if (XCheckMaskEvent(SaveDisplay, -1, &xevent) == False) {
31                         if (xsave.type) {
32                                 xevent = xsave;
33                                 xsave.type = 0;
34                                 aggMode = 0;
35                                 break;
36                         }
37                         threadWaitEvent(((_XPrivDisplay)SaveDisplay)->fd,
38                                         THWAIT_READ);
39                         continue;
40                 }
41
42                 /*
43                  * Aggregate exposure events.  This results in very efficient
44                  * display updates.
45                  */
46                 if (xevent.type == Expose && aggMode) {
47                         if (xsave.type == 0) {
48                                 xsave = xevent;
49                                 continue;
50                         }
51                         if (xsave.xany.window != xevent.xany.window)
52                                 break;
53                         if (xsave.xexpose.x > xevent.xexpose.x) {
54                                 xsave.xexpose.width += xsave.xexpose.x -
55                                                        xevent.xexpose.x;
56                                 xsave.xexpose.x = xevent.xexpose.x;
57                         }
58                         if (xsave.xexpose.x + xsave.xexpose.width <
59                                 xevent.xexpose.x + xevent.xexpose.width
60                         ) {
61                                 xsave.xexpose.width = xevent.xexpose.x +
62                                                       xevent.xexpose.width -
63                                                       xsave.xexpose.x;
64                         }
65                         if (xsave.xexpose.y > xevent.xexpose.y) {
66                                 xsave.xexpose.height += xsave.xexpose.y -
67                                                         xevent.xexpose.y;
68                                 xsave.xexpose.y = xevent.xexpose.y;
69                         }
70                         if (xsave.xexpose.y + xsave.xexpose.height <
71                                 xevent.xexpose.y + xevent.xexpose.height
72                         ) {
73                                 xsave.xexpose.height = xevent.xexpose.y + 
74                                                        xevent.xexpose.height -
75                                                        xsave.xexpose.y;
76                         }
77                         continue;
78                 }
79                 break;
80         }
81
82         /*
83          * Process and return the xevent.  Note that xsave may still be valid
84          * and we will hold it until the next request.
85          */
86         /*RuneRunTime_RSPut(res->s_RefStor);*/
87         event = heapAlloc(&ts->ts_Pointer, &EventType);
88         /* automatic RSGet by heapAlloc() */
89
90         event->ev_Type = xevent.type;
91         event->ev_XId = xevent.xany.window;
92         event->ev_FocusType = 0;
93         event->ev_Width = -1;
94         event->ev_Height = -1;
95
96         switch(xevent.type) {
97         case KeyPress:
98         case KeyRelease:
99                 {
100                         int modState = 0;
101                         KeySym key;
102
103                         event->ev_FocusType = 2;
104                         event->ev_MPos.x = xevent.xkey.x;
105                         event->ev_MPos.y = xevent.xkey.y;
106                         state = xevent.xkey.state;
107
108                         XLookupString(&xevent.xkey, &event->ev_KeyChar,
109                                       1, &key, NULL);
110
111                         switch(key) {
112                         case XK_Shift_L:
113                         case XK_Shift_R:
114                                 modState = ShiftMask;
115                                 break;
116                         case XK_Control_L:
117                         case XK_Control_R:
118                                 modState = ControlMask;
119                                 break;
120                         case XK_Caps_Lock:
121                                 modState = LockMask;
122                                 break;
123                         case XK_Shift_Lock:
124                                 /* XXX */
125                                 break;
126                         case XK_Meta_L:
127                         case XK_Meta_R:
128                                 /* XXX */
129                                 break;
130                         case XK_Alt_L:
131                         case XK_Alt_R:
132                                 modState = Mod1Mask;
133                                 break;
134                         case XK_Num_Lock:
135                                 modState = Mod2Mask;
136                                 break;
137                         case XK_Scroll_Lock:
138                                 modState = Mod5Mask;
139                                 break;
140                         case XK_Super_L:
141                         case XK_Super_R:
142                         case XK_Hyper_L:
143                         case XK_Hyper_R:
144                                 /* XXX */
145                                 break;
146                         }
147                         if (xevent.type == KeyRelease) {
148                                 event->ev_KeySym = -key;
149                                 state &= ~modState;
150                         } else {
151                                 event->ev_KeySym = key;
152                                 state |= modState;
153                         }
154                 }
155                 break;
156         case ButtonPress:
157                 event->ev_FocusType = 1;
158                 event->ev_MPos.x = xevent.xbutton.x;
159                 event->ev_MPos.y = xevent.xbutton.y;
160                 event->ev_KeySym = xevent.xbutton.button - Button1 +
161                                    XK_Pointer_Button1;
162                 state = xevent.xbutton.state | 
163                         (Button1Mask << (xevent.xbutton.button - Button1));
164                 break;
165         case ButtonRelease:
166                 event->ev_FocusType = 1;
167                 event->ev_MPos.x = xevent.xbutton.x;
168                 event->ev_MPos.y = xevent.xbutton.y;
169                 event->ev_KeySym = -(xevent.xkey.keycode - Button1 +
170                                      XK_Pointer_Button1);
171                 state = xevent.xkey.state &
172                         ~(Button1Mask << (xevent.xbutton.button - Button1));
173                 break;
174         case MotionNotify:
175                 event->ev_FocusType = 1;
176                 event->ev_MPos.x = xevent.xmotion.x;
177                 event->ev_MPos.y = xevent.xmotion.y;
178                 state = xevent.xmotion.state;
179                 break;
180         case EnterNotify:
181         case LeaveNotify:
182                 event->ev_FocusType = 1;
183                 event->ev_MPos.x = xevent.xcrossing.x;
184                 event->ev_MPos.y = xevent.xcrossing.y;
185                 state = xevent.xcrossing.state;
186                 break;
187         case FocusIn:
188         case FocusOut:
189         case KeymapNotify:
190                 break;
191         case Expose:
192                 event->ev_MPos.x = xevent.xexpose.x;
193                 event->ev_MPos.y = xevent.xexpose.y;
194                 event->ev_Width = xevent.xexpose.width;
195                 event->ev_Height = xevent.xexpose.height;
196                 event->ev_FocusType = 3;
197                 break;
198         case MapNotify:
199         case VisibilityNotify:
200                 event->ev_FocusType = 3;
201                 break;
202         case GraphicsExpose:
203                 break;
204         case NoExpose:
205                 event->ev_FocusType = 3;
206                 break;
207         case CreateNotify:
208         case DestroyNotify:
209         case UnmapNotify:
210         case MapRequest:
211         case ReparentNotify:
212                 break;
213         case ConfigureNotify:
214                 event->ev_MPos.x = xevent.xconfigure.x;
215                 event->ev_MPos.y = xevent.xconfigure.y;
216                 event->ev_Width = xevent.xconfigure.width;
217                 event->ev_Height = xevent.xconfigure.height;
218                 event->ev_FocusType = 4;
219                 break;
220         case ConfigureRequest:
221         case GravityNotify:
222         case ResizeRequest:
223         case CirculateNotify:
224         case CirculateRequest:
225         case PropertyNotify:
226         case SelectionClear:
227         case SelectionRequest:
228         case SelectionNotify:
229         case ColormapNotify:
230         case ClientMessage:
231         case MappingNotify:
232                 break;
233         }
234         event->ev_MetaMask = state;
235
236         data.data = &ts->ts_Pointer;
237         data.rs = NULL;
238
239         return data;
240 }