]> Dogcows Code - chaz/openbox/blob - otk/eventdispatcher.cc
offsets in planar surfaces
[chaz/openbox] / otk / eventdispatcher.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 #include "eventdispatcher.hh"
6 #include "display.hh"
7
8 #include <cstdio>
9 #include <iostream>
10
11 namespace otk {
12
13 EventDispatcher::EventDispatcher()
14 : _fallback(0), _master(0)
15 {
16 }
17
18 EventDispatcher::~EventDispatcher()
19 {
20 }
21
22 void EventDispatcher::clearAllHandlers(void)
23 {
24 _map.clear();
25 }
26
27 void EventDispatcher::registerHandler(Window id, EventHandler *handler)
28 {
29 _map.insert(std::pair<Window, EventHandler*>(id, handler));
30 }
31
32 void EventDispatcher::clearHandler(Window id)
33 {
34 _map.erase(id);
35 }
36
37 void EventDispatcher::dispatchEvents(bool remote)
38 {
39 XEvent e;
40
41 while (true) {
42 /*
43 There are slightly different event retrieval semantics here for local (or
44 high bandwidth) versus remote (or low bandwidth) connections to the
45 display/Xserver.
46 */
47 if (remote) {
48 if (!XPending(**display))
49 return;
50 } else {
51 /*
52 This XSync allows for far more compression of events, which makes
53 things like Motion events perform far far better. Since it also means
54 network traffic for every event instead of every X events (where X is
55 the number retrieved at a time), it probably should not be used for
56 setups where Openbox is running on a remote/low bandwidth
57 display/Xserver.
58 */
59 XSync(**display, false);
60 if (!XEventsQueued(**display, QueuedAlready))
61 return;
62 }
63 XNextEvent(**display, &e);
64
65 #if 0//defined(DEBUG)
66 printf("Event %d window %lx\n", e.type, e.xany.window);
67 #endif
68
69 if (e.type == FocusIn || e.type == FocusOut) {
70 // focus events are a beast all their own.. yuk, hate, etc.
71 dispatchFocus(e);
72 } else {
73 Window win;
74
75 // pick a window
76 switch (e.type) {
77 case UnmapNotify:
78 win = e.xunmap.window;
79 break;
80 case DestroyNotify:
81 win = e.xdestroywindow.window;
82 break;
83 case ConfigureRequest:
84 win = e.xconfigurerequest.window;
85 break;
86 default:
87 win = e.xany.window;
88 }
89
90 // grab the lasttime and hack up the modifiers
91 switch (e.type) {
92 case ButtonPress:
93 case ButtonRelease:
94 _lasttime = e.xbutton.time;
95 e.xbutton.state &= ~(LockMask | display->numLockMask() |
96 display->scrollLockMask());
97 break;
98 case KeyPress:
99 e.xkey.state &= ~(LockMask | display->numLockMask() |
100 display->scrollLockMask());
101 break;
102 case MotionNotify:
103 _lasttime = e.xmotion.time;
104 e.xmotion.state &= ~(LockMask | display->numLockMask() |
105 display->scrollLockMask());
106 break;
107 case PropertyNotify:
108 _lasttime = e.xproperty.time;
109 break;
110 case EnterNotify:
111 case LeaveNotify:
112 _lasttime = e.xcrossing.time;
113 if (e.xcrossing.mode != NotifyNormal)
114 continue; // skip me!
115 break;
116 }
117
118 dispatch(win, e);
119 }
120 }
121 }
122
123 void EventDispatcher::dispatchFocus(const XEvent &e)
124 {
125 // printf("focus %s detail %d -> 0x%lx\n",
126 // (e.xfocus.type == FocusIn ? "IN" : "OUT"),
127 // e.xfocus.detail, e.xfocus.window);
128 // ignore focus changes from grabs
129 if (e.xfocus.mode == NotifyGrab) //|| e.xfocus.mode == NotifyUngrab ||
130 // From Metacity, from WindowMaker, ignore all funky pointer root events
131 // its commented out cuz I don't think we need this at all. If problems
132 // arise we can look into it
133 //e.xfocus.detail > NotifyNonlinearVirtual)
134 return;
135
136 if (e.type == FocusIn) {
137 //printf("Got FocusIn!\n");
138
139 // send a FocusIn to whatever was just focused
140 dispatch(e.xfocus.window, e);
141 //printf("Sent FocusIn 0x%lx\n", e.xfocus.window);
142
143 } else if (e.type == FocusOut) {
144 //printf("Got FocusOut!\n");
145
146 // FocusOut events just make us look for FocusIn events. They are ignored
147 // otherwise.
148 XEvent fi;
149 if (XCheckTypedEvent(**display, FocusIn, &fi)) {
150 //printf("Found FocusIn\n");
151 dispatchFocus(fi);
152 // dont unfocus the window we just focused!
153 if (fi.xfocus.window == e.xfocus.window)
154 return;
155 }
156
157 dispatch(e.xfocus.window, e);
158 //printf("Sent FocusOut 0x%lx\n", e.xfocus.window);
159 }
160 }
161
162 void EventDispatcher::dispatch(Window win, const XEvent &e)
163 {
164 EventHandler *handler = 0;
165 EventMap::iterator it;
166
167 // master gets everything first
168 if (_master)
169 _master->handle(e);
170
171 // find handler for the chosen window
172 it = _map.find(win);
173
174 if (it != _map.end()) {
175 // if we found a handler
176 handler = it->second;
177 } else if (e.type == ConfigureRequest) {
178 // unhandled configure requests must be used to configure the window
179 // directly
180 XWindowChanges xwc;
181
182 xwc.x = e.xconfigurerequest.x;
183 xwc.y = e.xconfigurerequest.y;
184 xwc.width = e.xconfigurerequest.width;
185 xwc.height = e.xconfigurerequest.height;
186 xwc.border_width = e.xconfigurerequest.border_width;
187 xwc.sibling = e.xconfigurerequest.above;
188 xwc.stack_mode = e.xconfigurerequest.detail;
189
190 #ifdef DEBUG
191 printf("Proxying configure event for 0x%lx\n", e.xconfigurerequest.window);
192 #endif
193
194 // we are not to be held responsible if someone sends us an invalid
195 // request!
196 display->setIgnoreErrors(true);
197 XConfigureWindow(**display, e.xconfigurerequest.window,
198 e.xconfigurerequest.value_mask, &xwc);
199 display->setIgnoreErrors(false);
200 } else {
201 // grab a falback if it exists
202 handler = _fallback;
203 }
204
205 if (handler)
206 handler->handle(e);
207 }
208
209 EventHandler *EventDispatcher::findHandler(Window win)
210 {
211 EventMap::iterator it = _map.find(win);
212 if (it != _map.end())
213 return it->second;
214 return 0;
215 }
216
217 }
This page took 0.046529 seconds and 4 git commands to generate.