]> icculus.org git repositories - mikachu/openbox.git/blob - src/xeventhandler.cc
fix compiling with the new strut (new namespace)
[mikachu/openbox.git] / src / xeventhandler.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2
3 #include "xeventhandler.hh"
4 #include "client.hh"
5 #include "openbox.hh"
6 #include "otk/display.hh"
7 #include "otk/rect.hh"
8
9 namespace ob {
10
11
12 OBXEventHandler::OBXEventHandler()
13 {
14   _lasttime = 1; // 0 is CurrentTime, so set to minimum
15 }
16
17 void OBXEventHandler::buttonPress(const XButtonEvent &e)
18 {
19   _lasttime = e.time;
20
21 }
22
23
24 void OBXEventHandler::buttonRelease(const XButtonEvent &e)
25 {
26   _lasttime = e.time;
27
28 }
29
30
31 void OBXEventHandler::keyPress(const XKeyEvent &e)
32 {
33   _lasttime = e.time;
34 }
35
36
37 void OBXEventHandler::motion(const XMotionEvent &e)
38 {
39   _lasttime = e.time;
40
41   // the pointer is on the wrong screen
42   if (! e.same_screen) return;
43
44 }
45
46
47 void OBXEventHandler::enterNotify(const XCrossingEvent &e)
48 {
49   _lasttime = e.time;
50
51   OBClient *client = Openbox::instance->findClient(e.window);
52   if (!client) return;
53   
54 /*
55   BScreen *screen = (BScreen *) 0;
56   BlackboxWindow *win = (BlackboxWindow *) 0;
57
58   if (e->xcrossing.mode == NotifyGrab) break;
59
60   if ((e->xcrossing.window == e->xcrossing.root) &&
61       (screen = searchScreen(e->xcrossing.window))) {
62     screen->getImageControl()->installRootColormap();
63   } else if ((win = searchWindow(e->xcrossing.window))) {
64     if (! no_focus)
65       win->enterNotifyEvent(&e->xcrossing);
66   }
67 */
68 }
69
70
71 void OBXEventHandler::leaveNotify(const XCrossingEvent &e)
72 {
73   _lasttime = e.time;
74
75   OBClient *client = Openbox::instance->findClient(e.window);
76   if (!client) return;
77   
78 /*
79   BlackboxWindow *win = (BlackboxWindow *) 0;
80
81   if ((win = searchWindow(e->xcrossing.window)))
82     win->leaveNotifyEvent(&e->xcrossing);
83 */
84 }
85
86
87 void OBXEventHandler::configureRequest(const XConfigureRequestEvent &e)
88 {
89   OBClient *client = Openbox::instance->findClient(e.window);
90   if (!client) return;
91   
92 /*  BlackboxWindow *win = (BlackboxWindow *) 0;
93
94   if ((win = searchWindow(e->xconfigurerequest.window))) {
95     win->configureRequestEvent(&e->xconfigurerequest);
96   } else {
97     if (validateWindow(e->xconfigurerequest.window)) {
98       XWindowChanges xwc;
99
100       xwc.x = e->xconfigurerequest.x;
101       xwc.y = e->xconfigurerequest.y;
102       xwc.width = e->xconfigurerequest.width;
103       xwc.height = e->xconfigurerequest.height;
104       xwc.border_width = e->xconfigurerequest.border_width;
105       xwc.sibling = e->xconfigurerequest.above;
106       xwc.stack_mode = e->xconfigurerequest.detail;
107
108       XConfigureWindow(otk::OBDisplay::display, e->xconfigurerequest.window,
109                        e->xconfigurerequest.value_mask, &xwc);
110     }
111   }
112 */
113 }
114
115
116 void OBXEventHandler::mapRequest(const XMapRequestEvent &e)
117 {
118 #ifdef    DEBUG
119   printf("MapRequest for 0x%lx\n", e.window);
120 #endif // DEBUG
121
122   OBClient *client = Openbox::instance->findClient(e.window);
123
124   if (client) {
125     // XXX: uniconify and/or unshade the window
126   } else {
127     // XXX: manage the window, i.e. grab events n shit
128     Openbox::instance->addClient(e.window, new OBClient(e.window));
129   }
130   
131 /*
132   BlackboxWindow *win = searchWindow(e->xmaprequest.window);
133
134   if (win) {
135     bool focus = False;
136     if (win->isIconic()) {
137       win->deiconify();
138       focus = True;
139     }
140     if (win->isShaded()) {
141       win->shade();
142       focus = True;
143     }
144
145     if (focus && (win->isTransient() || win->getScreen()->doFocusNew()) &&
146         win->isVisible())
147       win->setInputFocus();
148   } else {
149     BScreen *screen = searchScreen(e->xmaprequest.parent);
150
151     if (! screen) {
152 */
153       /*
154         we got a map request for a window who's parent isn't root. this
155         can happen in only one circumstance:
156
157         a client window unmapped a managed window, and then remapped it
158         somewhere between unmapping the client window and reparenting it
159         to root.
160
161         regardless of how it happens, we need to find the screen that
162         the window is on
163       */
164 /*
165       XWindowAttributes wattrib;
166       if (! XGetWindowAttributes(otk::OBDisplay::display,
167                                  e->xmaprequest.window,
168                                  &wattrib)) {
169         // failed to get the window attributes, perhaps the window has
170         // now been destroyed?
171         break;
172       }
173
174       screen = searchScreen(wattrib.root);
175       assert(screen != 0); // this should never happen
176     }
177     screen->manageWindow(e->xmaprequest.window);
178   }
179 */
180 }
181
182
183 void OBXEventHandler::unmapNotify(const XUnmapEvent &e)
184 {
185   OBClient *client = Openbox::instance->findClient(e.window);
186   if (!client) return;
187   
188   // XXX: unmanage the window, i.e. ungrab events n reparent n shit
189   Openbox::instance->removeClient(e.window);
190 }
191
192
193 void OBXEventHandler::destroyNotify(const XDestroyWindowEvent &e)
194 {
195   // XXX: window group leaders can come through here too!
196   
197   OBClient *client = Openbox::instance->findClient(e.window);
198   if (!client) return;
199   
200   // XXX: unmanage the window, i.e. ungrab events n reparent n shit
201   Openbox::instance->removeClient(e.window);
202 }
203
204
205 void OBXEventHandler::reparentNotify(const XReparentEvent &e)
206 {
207   /*
208     this event is quite rare and is usually handled in unmapNotify
209     however, if the window is unmapped when the reparent event occurs
210     the window manager never sees it because an unmap event is not sent
211     to an already unmapped window.
212   */
213   OBClient *client = Openbox::instance->findClient(e.window);
214   if (!client) return;
215
216 /*
217   BlackboxWindow *win = searchWindow(e->xreparent.window);
218   if (win)
219     win->reparentNotifyEvent(&e->xreparent);
220 */
221 }
222
223
224 void OBXEventHandler::propertyNotify(const XPropertyEvent &e)
225 {
226   _lasttime = e.time;
227
228   OBClient *client = Openbox::instance->findClient(e.window);
229   if (!client) return;
230
231   client->update(e);
232 }
233
234
235 void OBXEventHandler::expose(const XExposeEvent &first)
236 {
237   OBClient *client = Openbox::instance->findClient(first.window);
238   if (!client) return;
239
240   // compress expose events
241   XEvent e; e.xexpose = first;
242   unsigned int i = 0;
243   otk::Rect area(e.xexpose.x, e.xexpose.y, e.xexpose.width,
244                  e.xexpose.height);
245   while (XCheckTypedWindowEvent(otk::OBDisplay::display,
246                                 e.xexpose.window, Expose, &e)) {
247     i++;
248     // merge expose area
249     area |= otk::Rect(e.xexpose.x, e.xexpose.y, e.xexpose.width,
250                       e.xexpose.height);
251   }
252   if ( i > 0 ) {
253     // use the merged area
254     e.xexpose.x = area.x();
255     e.xexpose.y = area.y();
256     e.xexpose.width = area.width();
257     e.xexpose.height = area.height();
258   }
259
260   // XXX: make the decorations redraw!
261 }
262
263
264 void OBXEventHandler::colormapNotify(const XColormapEvent &e)
265 {
266   (void)e;
267 /*
268   BScreen *screen = searchScreen(e->xcolormap.window);
269   if (screen)
270     screen->setRootColormapInstalled((e->xcolormap.state ==
271                                       ColormapInstalled) ? True : False);
272 */
273 }
274
275
276 void OBXEventHandler::focusIn(const XFocusChangeEvent &e)
277 {
278   if (e.detail != NotifyNonlinear &&
279       e.detail != NotifyAncestor) {
280     /*
281       don't process FocusIns when:
282       1. the new focus window isn't an ancestor or inferior of the old
283       focus window (NotifyNonlinear)
284       make sure to allow the FocusIn when the old focus window was an
285       ancestor but didn't have a parent, such as root (NotifyAncestor)
286     */
287     return;
288   }
289 /*
290   BlackboxWindow *win = searchWindow(e.window);
291   if (win) {
292     if (! win->isFocused())
293       win->setFocusFlag(True);
294 */
295     /*
296       set the event window to None.  when the FocusOut event handler calls
297       this function recursively, it uses this as an indication that focus
298       has moved to a known window.
299     */
300 /*
301     e->xfocus.window = None;
302
303     no_focus = False;   // focusing is back on
304   }
305 */
306 }
307
308
309 void OBXEventHandler::focusOut(const XFocusChangeEvent &e)
310 {
311   if (e.detail != NotifyNonlinear) {
312     /*
313       don't process FocusOuts when:
314       2. the new focus window isn't an ancestor or inferior of the old
315       focus window (NotifyNonlinear)
316     */
317     return;
318   }
319
320 /*
321   BlackboxWindow *win = searchWindow(e->xfocus.window);
322   if (win && win->isFocused()) {
323 */
324     /*
325       before we mark "win" as unfocused, we need to verify that focus is
326       going to a known location, is in a known location, or set focus
327       to a known location.
328     */
329 /*
330     XEvent event;
331     // don't check the current focus if FocusOut was generated during a grab
332     bool check_focus = (e->xfocus.mode == NotifyNormal);
333 */
334     /*
335       First, check if there is a pending FocusIn event waiting.  if there
336       is, process it and determine if focus has moved to another window
337       (the FocusIn event handler sets the window in the event
338       structure to None to indicate this).
339     */
340 /*
341     if (XCheckTypedEvent(otk::OBDisplay::display, FocusIn, &event)) {
342
343       process_event(&event);
344       if (event.xfocus.window == None) {
345         // focus has moved
346         check_focus = False;
347       }
348     }
349
350     if (check_focus) {
351 */
352       /*
353         Second, we query the X server for the current input focus.
354         to make sure that we keep a consistent state.
355       */
356 /*
357       BlackboxWindow *focus;
358       Window w;
359       int revert;
360       XGetInputFocus(otk::OBDisplay::display, &w, &revert);
361       focus = searchWindow(w);
362       if (focus) {
363 */
364         /*
365           focus got from "win" to "focus" under some very strange
366           circumstances, and we need to make sure that the focus indication
367           is correct.
368         */
369 /*
370         setFocusedWindow(focus);
371       } else {
372         // we have no idea where focus went... so we set it to somewhere
373         setFocusedWindow(0);
374       }
375     }
376   }
377 */
378 }
379
380
381 #ifdef    SHAPE
382 void OBXEventHandler::shapeEvent(const XShapeEvent &e)
383 {
384   XShapeEvent *shape_event = (XShapeEvent *) e;
385   BlackboxWindow *win = searchWindow(e->xany.window);
386
387   if (win && shape_event->kind == ShapeBounding)
388     win->shapeEvent(shape_event);
389 }
390 #endif // SHAPE
391
392
393 void OBXEventHandler::clientMessage(const XClientMessageEvent &e)
394 {
395   if (e.format != 32)
396     return;
397 /*  
398   } else if (e->xclient.message_type == 
399              xatom->getAtom(XAtom::blackbox_change_workspace) || 
400              e->xclient.message_type == 
401              xatom->getAtom(XAtom::net_current_desktop)) {
402     // NET_CURRENT_DESKTOP message
403     BScreen *screen = searchScreen(e->xclient.window);
404
405     unsigned int workspace = e->xclient.data.l[0];
406     if (screen && workspace < screen->getWorkspaceCount())
407       screen->changeWorkspaceID(workspace);
408   } else if (e->xclient.message_type == 
409              xatom->getAtom(XAtom::net_active_window)) {
410     // NET_ACTIVE_WINDOW
411     BlackboxWindow *win = searchWindow(e->xclient.window);
412
413     if (win) {
414       BScreen *screen = win->getScreen();
415
416       if (win->isIconic())
417         win->deiconify(False, False);
418       if (! win->isStuck() &&
419           (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
420         no_focus = True;
421         screen->changeWorkspaceID(win->getWorkspaceNumber());
422       }
423       if (win->isVisible() && win->setInputFocus()) {
424         win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
425           raiseWindow(win);
426         win->installColormap(True);
427       }
428     }
429   } else if (e->xclient.message_type == 
430              xatom->getAtom(XAtom::net_number_of_desktops)) {
431     // NET_NUMBER_OF_DESKTOPS
432     BScreen *screen = searchScreen(e->xclient.window);
433         
434     if (e->xclient.data.l[0] > 0)
435       screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
436   } else if (e->xclient.message_type ==
437              xatom->getAtom(XAtom::net_close_window)) {
438     // NET_CLOSE_WINDOW
439     BlackboxWindow *win = searchWindow(e->xclient.window);
440     if (win && win->validateClient())
441       win->close(); // could this be smarter?
442   } else if (e->xclient.message_type ==
443              xatom->getAtom(XAtom::net_wm_moveresize)) {
444     // NET_WM_MOVERESIZE
445     BlackboxWindow *win = searchWindow(e->xclient.window);
446     if (win && win->validateClient()) {
447       int x_root = e->xclient.data.l[0],
448         y_root = e->xclient.data.l[1];
449       if ((Atom) e->xclient.data.l[2] ==
450           xatom->getAtom(XAtom::net_wm_moveresize_move)) {
451         win->beginMove(x_root, y_root);
452       } else {
453         if ((Atom) e->xclient.data.l[2] ==
454             xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
455           win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
456         else if ((Atom) e->xclient.data.l[2] ==
457                  xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
458           win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
459         else if ((Atom) e->xclient.data.l[2] ==
460                  xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
461           win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
462         else if ((Atom) e->xclient.data.l[2] ==
463                  xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
464           win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
465       }
466     }
467   }
468 */
469 }
470
471
472 void OBXEventHandler::handle(const XEvent &e)
473 {
474   /* mouse button events can get translated into:
475        press - button was pressed down
476        release - buttons was released
477        click - button was pressed and released on the same window
478        double click - clicked twice on the same widget in a given time and area
479
480      key events are only bindable to presses. key releases are ignored.
481
482      mouse enter/leave can be bound to for the entire window
483   */
484   
485   switch (e.type) {
486
487     // These types of XEvent's can be bound to actions by the user, and so end
488     // up getting passed off to the OBBindingMapper class at some point
489   case ButtonPress:
490     buttonPress(e.xbutton);
491     break;
492   case ButtonRelease:
493     buttonRelease(e.xbutton);
494     break;
495   case KeyPress:
496     keyPress(e.xkey);
497     break;
498   case MotionNotify:
499     motion(e.xmotion);
500     break;
501   case EnterNotify:
502     enterNotify(e.xcrossing);
503     break;
504   case LeaveNotify:
505     leaveNotify(e.xcrossing);
506     break;
507
508
509     // These types of XEvent's can not be bound to actions by the user and so
510     // will simply be handled in this class
511   case ConfigureRequest:
512     configureRequest(e.xconfigurerequest);
513     break;
514
515   case MapRequest:
516     mapRequest(e.xmaprequest);
517     break;
518     
519   case UnmapNotify:
520     unmapNotify(e.xunmap);
521     break;
522
523   case DestroyNotify:
524     destroyNotify(e.xdestroywindow);
525     break;
526
527   case ReparentNotify:
528     reparentNotify(e.xreparent);
529     break;
530
531   case PropertyNotify:
532     propertyNotify(e.xproperty);
533     break;
534
535   case Expose:
536     expose(e.xexpose);
537     break;
538
539   case ColormapNotify:
540     colormapNotify(e.xcolormap);
541     break;
542     
543   case FocusIn:
544     focusIn(e.xfocus);
545     break;
546
547   case FocusOut:
548     focusOut(e.xfocus);
549     break;
550
551   case ClientMessage:
552     clientMessage(e.xclient);
553
554   default:
555 #ifdef    SHAPE
556     if (e.type == otk::OBDisplay::shapeEventBase())
557       shapeEvent(e);
558 #endif // SHAPE
559     break;
560     
561 /*
562   case ClientMessage: {
563     break;
564   }
565
566 */
567   } // switch
568 }
569
570
571 }