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