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