00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 # include "../config.h"
00005 #endif
00006
00007 #include "eventdispatcher.hh"
00008 #include "display.hh"
00009
00010 extern "C" {
00011 #ifdef HAVE_STDIO_H
00012 # include <stdio.h>
00013 #endif
00014 }
00015
00016 #include <iostream>
00017
00018 namespace otk {
00019
00020 EventDispatcher::EventDispatcher()
00021 : _fallback(0), _master(0)
00022 {
00023 }
00024
00025 EventDispatcher::~EventDispatcher()
00026 {
00027 }
00028
00029 void EventDispatcher::clearAllHandlers(void)
00030 {
00031 _map.clear();
00032 }
00033
00034 void EventDispatcher::registerHandler(Window id, EventHandler *handler)
00035 {
00036 _map.insert(std::pair<Window, EventHandler*>(id, handler));
00037 }
00038
00039 void EventDispatcher::clearHandler(Window id)
00040 {
00041 _map.erase(id);
00042 }
00043
00044 void EventDispatcher::dispatchEvents(void)
00045 {
00046 XEvent e;
00047
00048 while (XPending(**display)) {
00049 XNextEvent(**display, &e);
00050
00051 #if 0//defined(DEBUG)
00052 printf("Event %d window %lx\n", e.type, e.xany.window);
00053 #endif
00054
00055 if (e.type == FocusIn || e.type == FocusOut) {
00056
00057 dispatchFocus(e);
00058 } else {
00059 Window win;
00060
00061
00062 switch (e.type) {
00063 case UnmapNotify:
00064 win = e.xunmap.window;
00065 break;
00066 case DestroyNotify:
00067 win = e.xdestroywindow.window;
00068 break;
00069 case ConfigureRequest:
00070 win = e.xconfigurerequest.window;
00071 break;
00072 default:
00073 win = e.xany.window;
00074 }
00075
00076
00077 switch (e.type) {
00078 case ButtonPress:
00079 case ButtonRelease:
00080 _lasttime = e.xbutton.time;
00081 e.xbutton.state &= ~(LockMask | display->numLockMask() |
00082 display->scrollLockMask());
00083 break;
00084 case KeyPress:
00085 e.xkey.state &= ~(LockMask | display->numLockMask() |
00086 display->scrollLockMask());
00087 break;
00088 case MotionNotify:
00089 _lasttime = e.xmotion.time;
00090 e.xmotion.state &= ~(LockMask | display->numLockMask() |
00091 display->scrollLockMask());
00092 break;
00093 case PropertyNotify:
00094 _lasttime = e.xproperty.time;
00095 break;
00096 case EnterNotify:
00097 case LeaveNotify:
00098 _lasttime = e.xcrossing.time;
00099 if (e.xcrossing.mode != NotifyNormal)
00100 continue;
00101 break;
00102 }
00103
00104 dispatch(win, e);
00105 }
00106 }
00107 }
00108
00109 void EventDispatcher::dispatchFocus(const XEvent &e)
00110 {
00111
00112
00113
00114
00115 if (e.xfocus.mode == NotifyGrab)
00116
00117
00118
00119
00120 return;
00121
00122 if (e.type == FocusIn) {
00123
00124
00125
00126 dispatch(e.xfocus.window, e);
00127
00128
00129 } else if (e.type == FocusOut) {
00130
00131
00132
00133
00134 XEvent fi;
00135 if (XCheckTypedEvent(**display, FocusIn, &fi)) {
00136
00137 dispatchFocus(fi);
00138
00139 if (fi.xfocus.window == e.xfocus.window)
00140 return;
00141 }
00142
00143 dispatch(e.xfocus.window, e);
00144
00145 }
00146 }
00147
00148 void EventDispatcher::dispatch(Window win, const XEvent &e)
00149 {
00150 EventHandler *handler = 0;
00151 EventMap::iterator it;
00152
00153
00154 if (_master)
00155 _master->handle(e);
00156
00157
00158 it = _map.find(win);
00159
00160 if (it != _map.end()) {
00161
00162 handler = it->second;
00163 } else if (e.type == ConfigureRequest) {
00164
00165
00166 XWindowChanges xwc;
00167
00168 xwc.x = e.xconfigurerequest.x;
00169 xwc.y = e.xconfigurerequest.y;
00170 xwc.width = e.xconfigurerequest.width;
00171 xwc.height = e.xconfigurerequest.height;
00172 xwc.border_width = e.xconfigurerequest.border_width;
00173 xwc.sibling = e.xconfigurerequest.above;
00174 xwc.stack_mode = e.xconfigurerequest.detail;
00175
00176 #ifdef DEBUG
00177 printf("Proxying configure event for 0x%lx\n", e.xconfigurerequest.window);
00178 #endif
00179
00180
00181
00182 display->setIgnoreErrors(true);
00183 XConfigureWindow(**display, e.xconfigurerequest.window,
00184 e.xconfigurerequest.value_mask, &xwc);
00185 display->setIgnoreErrors(false);
00186 } else {
00187
00188 handler = _fallback;
00189 }
00190
00191 if (handler)
00192 handler->handle(e);
00193 }
00194
00195 EventHandler *EventDispatcher::findHandler(Window win)
00196 {
00197 EventMap::iterator it = _map.find(win);
00198 if (it != _map.end())
00199 return it->second;
00200 return 0;
00201 }
00202
00203 }