1/*
2
3Copyright 1993 by Davor Matic
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and that
8both that copyright notice and this permission notice appear in
9supporting documentation.  Davor Matic makes no representations about
10the suitability of this software for any purpose.  It is provided "as
11is" without express or implied warranty.
12
13*/
14
15#ifdef HAVE_XNEST_CONFIG_H
16#include <xnest-config.h>
17#endif
18
19#include <X11/X.h>
20#include <X11/Xproto.h>
21#include "screenint.h"
22#include "input.h"
23#include "misc.h"
24#include "scrnintstr.h"
25#include "windowstr.h"
26#include "servermd.h"
27#include "inputstr.h"
28#include "inpututils.h"
29
30#include "mi.h"
31
32#include "Xnest.h"
33
34#include "Args.h"
35#include "Color.h"
36#include "Display.h"
37#include "Screen.h"
38#include "XNWindow.h"
39#include "Events.h"
40#include "Keyboard.h"
41#include "Pointer.h"
42#include "mipointer.h"
43
44CARD32 lastEventTime = 0;
45
46void
47ProcessInputEvents(void)
48{
49    mieqProcessInputEvents();
50}
51
52int
53TimeSinceLastInputEvent(void)
54{
55    if (lastEventTime == 0)
56        lastEventTime = GetTimeInMillis();
57    return GetTimeInMillis() - lastEventTime;
58}
59
60void
61SetTimeSinceLastInputEvent(void)
62{
63    lastEventTime = GetTimeInMillis();
64}
65
66static Bool
67xnestExposurePredicate(Display * dpy, XEvent * event, char *args)
68{
69    return event->type == Expose || event->type == ProcessedExpose;
70}
71
72static Bool
73xnestNotExposurePredicate(Display * dpy, XEvent * event, char *args)
74{
75    return !xnestExposurePredicate(dpy, event, args);
76}
77
78void
79xnestCollectExposures(void)
80{
81    XEvent X;
82    WindowPtr pWin;
83    RegionRec Rgn;
84    BoxRec Box;
85
86    while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) {
87        pWin = xnestWindowPtr(X.xexpose.window);
88
89        if (pWin && X.xexpose.width && X.xexpose.height) {
90            Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x;
91            Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y;
92            Box.x2 = Box.x1 + X.xexpose.width;
93            Box.y2 = Box.y1 + X.xexpose.height;
94
95            RegionInit(&Rgn, &Box, 1);
96
97            miSendExposures(pWin, &Rgn, Box.x1, Box.y1);
98        }
99    }
100}
101
102void
103xnestQueueKeyEvent(int type, unsigned int keycode)
104{
105    lastEventTime = GetTimeInMillis();
106    QueueKeyboardEvents(xnestKeyboardDevice, type, keycode);
107}
108
109void
110xnestCollectEvents(void)
111{
112    XEvent X;
113    int valuators[2];
114    ValuatorMask mask;
115    ScreenPtr pScreen;
116
117    while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) {
118        switch (X.type) {
119        case KeyPress:
120            xnestUpdateModifierState(X.xkey.state);
121            xnestQueueKeyEvent(KeyPress, X.xkey.keycode);
122            break;
123
124        case KeyRelease:
125            xnestUpdateModifierState(X.xkey.state);
126            xnestQueueKeyEvent(KeyRelease, X.xkey.keycode);
127            break;
128
129        case ButtonPress:
130            valuator_mask_set_range(&mask, 0, 0, NULL);
131            xnestUpdateModifierState(X.xkey.state);
132            lastEventTime = GetTimeInMillis();
133            QueuePointerEvents(xnestPointerDevice, ButtonPress,
134                               X.xbutton.button, POINTER_RELATIVE, &mask);
135            break;
136
137        case ButtonRelease:
138            valuator_mask_set_range(&mask, 0, 0, NULL);
139            xnestUpdateModifierState(X.xkey.state);
140            lastEventTime = GetTimeInMillis();
141            QueuePointerEvents(xnestPointerDevice, ButtonRelease,
142                               X.xbutton.button, POINTER_RELATIVE, &mask);
143            break;
144
145        case MotionNotify:
146            valuators[0] = X.xmotion.x;
147            valuators[1] = X.xmotion.y;
148            valuator_mask_set_range(&mask, 0, 2, valuators);
149            lastEventTime = GetTimeInMillis();
150            QueuePointerEvents(xnestPointerDevice, MotionNotify,
151                               0, POINTER_ABSOLUTE, &mask);
152            break;
153
154        case FocusIn:
155            if (X.xfocus.detail != NotifyInferior) {
156                pScreen = xnestScreen(X.xfocus.window);
157                if (pScreen)
158                    xnestDirectInstallColormaps(pScreen);
159            }
160            break;
161
162        case FocusOut:
163            if (X.xfocus.detail != NotifyInferior) {
164                pScreen = xnestScreen(X.xfocus.window);
165                if (pScreen)
166                    xnestDirectUninstallColormaps(pScreen);
167            }
168            break;
169
170        case KeymapNotify:
171            break;
172
173        case EnterNotify:
174            if (X.xcrossing.detail != NotifyInferior) {
175                pScreen = xnestScreen(X.xcrossing.window);
176                if (pScreen) {
177                    NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x,
178                                     X.xcrossing.y);
179                    valuators[0] = X.xcrossing.x;
180                    valuators[1] = X.xcrossing.y;
181                    valuator_mask_set_range(&mask, 0, 2, valuators);
182                    lastEventTime = GetTimeInMillis();
183                    QueuePointerEvents(xnestPointerDevice, MotionNotify,
184                                       0, POINTER_ABSOLUTE, &mask);
185                    xnestDirectInstallColormaps(pScreen);
186                }
187            }
188            break;
189
190        case LeaveNotify:
191            if (X.xcrossing.detail != NotifyInferior) {
192                pScreen = xnestScreen(X.xcrossing.window);
193                if (pScreen) {
194                    xnestDirectUninstallColormaps(pScreen);
195                }
196            }
197            break;
198
199        case DestroyNotify:
200            if (xnestParentWindow != (Window) 0 &&
201                X.xdestroywindow.window == xnestParentWindow)
202                exit(0);
203            break;
204
205        case CirculateNotify:
206        case ConfigureNotify:
207        case GravityNotify:
208        case MapNotify:
209        case ReparentNotify:
210        case UnmapNotify:
211            break;
212
213        default:
214            ErrorF("xnest warning: unhandled event\n");
215            break;
216        }
217    }
218}
219