Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

/otk/eventdispatcher.cc

Go to the documentation of this file.
00001 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
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       // focus events are a beast all their own.. yuk, hate, etc.
00057       dispatchFocus(e);
00058     } else {    
00059       Window win;
00060 
00061       // pick a window
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       // grab the lasttime and hack up the modifiers
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; // skip me!
00101         break;
00102       }
00103 
00104       dispatch(win, e);
00105     }
00106   }
00107 }
00108 
00109 void EventDispatcher::dispatchFocus(const XEvent &e)
00110 {
00111 //  printf("focus %s detail %d -> 0x%lx\n",
00112 //         (e.xfocus.type == FocusIn ? "IN" : "OUT"),
00113 //         e.xfocus.detail, e.xfocus.window);
00114   // ignore focus changes from grabs
00115   if (e.xfocus.mode == NotifyGrab) //|| e.xfocus.mode == NotifyUngrab ||
00116       // From Metacity, from WindowMaker, ignore all funky pointer root events
00117       // its commented out cuz I don't think we need this at all. If problems
00118       // arise we can look into it
00119       //e.xfocus.detail > NotifyNonlinearVirtual)
00120     return;
00121   
00122   if (e.type == FocusIn) {
00123     //printf("Got FocusIn!\n");
00124 
00125     // send a FocusIn to whatever was just focused
00126     dispatch(e.xfocus.window, e);
00127     //printf("Sent FocusIn 0x%lx\n", e.xfocus.window);
00128 
00129   } else if (e.type == FocusOut) {
00130     //printf("Got FocusOut!\n");
00131 
00132     // FocusOut events just make us look for FocusIn events. They are ignored
00133     // otherwise.
00134     XEvent fi;
00135     if (XCheckTypedEvent(**display, FocusIn, &fi)) {
00136       //printf("Found FocusIn\n");
00137       dispatchFocus(fi);
00138       // dont unfocus the window we just focused!
00139       if (fi.xfocus.window == e.xfocus.window)
00140         return;
00141     }
00142 
00143     dispatch(e.xfocus.window, e);
00144     //printf("Sent FocusOut 0x%lx\n", e.xfocus.window);
00145   }
00146 }
00147 
00148 void EventDispatcher::dispatch(Window win, const XEvent &e)
00149 {
00150   EventHandler *handler = 0;
00151   EventMap::iterator it;
00152 
00153   // master gets everything first
00154   if (_master)
00155     _master->handle(e);
00156 
00157   // find handler for the chosen window
00158   it = _map.find(win);
00159 
00160   if (it != _map.end()) {
00161     // if we found a handler
00162     handler = it->second;
00163   } else if (e.type == ConfigureRequest) {
00164     // unhandled configure requests must be used to configure the window
00165     // directly
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     // we are not to be held responsible if someone sends us an invalid
00181     // request!
00182     display->setIgnoreErrors(true); 
00183     XConfigureWindow(**display, e.xconfigurerequest.window,
00184                      e.xconfigurerequest.value_mask, &xwc);
00185     display->setIgnoreErrors(false);
00186   } else {
00187     // grab a falback if it exists
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 }

Generated on Tue Feb 4 22:58:55 2003 for Openbox by doxygen1.3-rc2