]> icculus.org git repositories - mikachu/openbox.git/blob - src/xeventhandler.cc
xeventhandler can handle everything except client messages now.
[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::handle(const XEvent &e)
388 {
389   /* mouse button events can get translated into:
390        press - button was pressed down
391        release - buttons was released
392        click - button was pressed and released on the same window
393        double click - clicked twice on the same widget in a given time and area
394
395      key events are only bindable to presses. key releases are ignored.
396
397      mouse enter/leave can be bound to for the entire window
398   */
399   
400   switch (e.type) {
401
402     // These types of XEvent's can be bound to actions by the user, and so end
403     // up getting passed off to the OBBindingMapper class at some point
404   case ButtonPress:
405     buttonPress(e.xbutton);
406     break;
407   case ButtonRelease:
408     buttonRelease(e.xbutton);
409     break;
410   case KeyPress:
411     keyPress(e.xkey);
412     break;
413   case MotionNotify:
414     motion(e.xmotion);
415     break;
416   case EnterNotify:
417     enterNotify(e.xcrossing);
418     break;
419   case LeaveNotify:
420     leaveNotify(e.xcrossing);
421     break;
422
423
424     // These types of XEvent's can not be bound to actions by the user and so
425     // will simply be handled in this class
426   case ConfigureRequest:
427     configureRequest(e.xconfigurerequest);
428     break;
429
430   case MapRequest:
431     mapRequest(e.xmaprequest);
432     break;
433     
434   case UnmapNotify:
435     unmapNotify(e.xunmap);
436     break;
437
438   case DestroyNotify:
439     destroyNotify(e.xdestroywindow);
440     break;
441
442   case ReparentNotify:
443     reparentNotify(e.xreparent);
444     break;
445
446   case PropertyNotify:
447     propertyNotify(e.xproperty);
448     break;
449
450   case Expose:
451     expose(e.xexpose);
452     break;
453
454   case ColormapNotify:
455     colormapNotify(e.xcolormap);
456     break;
457     
458   case FocusIn:
459     focusIn(e.xfocus);
460     break;
461
462   case FocusOut:
463     focusOut(e.xfocus);
464     break;
465
466   default:
467 #ifdef    SHAPE
468     if (e.type == otk::OBDisplay::shapeEventBase())
469       shapeEvent(e);
470 #endif // SHAPE
471     break;
472     
473 /*
474   case ClientMessage: {
475     if (e->xclient.format == 32) {
476       if (e->xclient.message_type == xatom->getAtom(XAtom::wm_change_state)) {
477         // WM_CHANGE_STATE message
478         BlackboxWindow *win = searchWindow(e->xclient.window);
479         if (! win || ! win->validateClient()) return;
480
481         if (e->xclient.data.l[0] == IconicState)
482           win->iconify();
483         if (e->xclient.data.l[0] == NormalState)
484           win->deiconify();
485       } else if (e->xclient.message_type == 
486                  xatom->getAtom(XAtom::blackbox_change_workspace) || 
487                  e->xclient.message_type == 
488                  xatom->getAtom(XAtom::net_current_desktop)) {
489         // NET_CURRENT_DESKTOP message
490         BScreen *screen = searchScreen(e->xclient.window);
491
492         unsigned int workspace = e->xclient.data.l[0];
493         if (screen && workspace < screen->getWorkspaceCount())
494           screen->changeWorkspaceID(workspace);
495       } else if (e->xclient.message_type == 
496                  xatom->getAtom(XAtom::blackbox_change_window_focus)) {
497         // TEMP HACK TO KEEP BBKEYS WORKING
498         BlackboxWindow *win = searchWindow(e->xclient.window);
499
500         if (win && win->isVisible() && win->setInputFocus())
501           win->installColormap(True);
502       } else if (e->xclient.message_type == 
503                  xatom->getAtom(XAtom::net_active_window)) {
504         // NET_ACTIVE_WINDOW
505         BlackboxWindow *win = searchWindow(e->xclient.window);
506
507         if (win) {
508           BScreen *screen = win->getScreen();
509
510           if (win->isIconic())
511             win->deiconify(False, False);
512           if (! win->isStuck() &&
513               (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
514             no_focus = True;
515             screen->changeWorkspaceID(win->getWorkspaceNumber());
516           }
517           if (win->isVisible() && win->setInputFocus()) {
518             win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
519               raiseWindow(win);
520             win->installColormap(True);
521           }
522         }
523       } else if (e->xclient.message_type == 
524                  xatom->getAtom(XAtom::blackbox_cycle_window_focus)) {
525         // BLACKBOX_CYCLE_WINDOW_FOCUS
526         BScreen *screen = searchScreen(e->xclient.window);
527
528         if (screen) {
529           if (! e->xclient.data.l[0])
530             screen->prevFocus();
531           else
532             screen->nextFocus();
533         }
534       } else if (e->xclient.message_type == 
535                  xatom->getAtom(XAtom::net_wm_desktop)) {
536         // NET_WM_DESKTOP
537         BlackboxWindow *win = searchWindow(e->xclient.window);
538
539         if (win) {
540           BScreen *screen = win->getScreen();
541           unsigned long wksp = (unsigned) e->xclient.data.l[0];
542           if (wksp < screen->getWorkspaceCount()) {
543             if (win->isIconic()) win->deiconify(False, True);
544             if (win->isStuck()) win->stick();
545             if (wksp != screen->getCurrentWorkspaceID())
546               win->withdraw();
547             else
548               win->show();
549             screen->reassociateWindow(win, wksp, True);
550           } else if (wksp == 0xfffffffe || // XXX: BUG, BUT DOING THIS SO KDE WORKS FOR NOW!!
551                      wksp == 0xffffffff) {
552             if (win->isIconic()) win->deiconify(False, True);
553             if (! win->isStuck()) win->stick();
554             if (! win->isVisible()) win->show();
555           }
556         }
557       } else if (e->xclient.message_type == 
558                  xatom->getAtom(XAtom::blackbox_change_attributes)) {
559         // BLACKBOX_CHANGE_ATTRIBUTES
560         BlackboxWindow *win = searchWindow(e->xclient.window);
561
562         if (win && win->validateClient()) {
563           BlackboxHints net;
564           net.flags = e->xclient.data.l[0];
565           net.attrib = e->xclient.data.l[1];
566           net.workspace = e->xclient.data.l[2];
567           net.stack = e->xclient.data.l[3];
568           net.decoration = e->xclient.data.l[4];
569
570           win->changeBlackboxHints(&net);
571         }
572       } else if (e->xclient.message_type == 
573                 xatom->getAtom(XAtom::net_number_of_desktops)) {
574         // NET_NUMBER_OF_DESKTOPS
575         BScreen *screen = searchScreen(e->xclient.window);
576         
577         if (e->xclient.data.l[0] > 0)
578           screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
579       } else if (e->xclient.message_type ==
580                  xatom->getAtom(XAtom::net_close_window)) {
581         // NET_CLOSE_WINDOW
582         BlackboxWindow *win = searchWindow(e->xclient.window);
583         if (win && win->validateClient())
584           win->close(); // could this be smarter?
585       } else if (e->xclient.message_type ==
586                  xatom->getAtom(XAtom::net_wm_moveresize)) {
587         // NET_WM_MOVERESIZE
588         BlackboxWindow *win = searchWindow(e->xclient.window);
589         if (win && win->validateClient()) {
590           int x_root = e->xclient.data.l[0],
591               y_root = e->xclient.data.l[1];
592           if ((Atom) e->xclient.data.l[2] ==
593               xatom->getAtom(XAtom::net_wm_moveresize_move)) {
594             win->beginMove(x_root, y_root);
595           } else {
596             if ((Atom) e->xclient.data.l[2] ==
597                 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
598               win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
599             else if ((Atom) e->xclient.data.l[2] ==
600                      xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
601               win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
602             else if ((Atom) e->xclient.data.l[2] ==
603                      xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
604               win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
605             else if ((Atom) e->xclient.data.l[2] ==
606                 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
607               win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
608           }
609         }
610       } else if (e->xclient.message_type ==
611                  xatom->getAtom(XAtom::net_wm_state)) {
612         // NET_WM_STATE
613         BlackboxWindow *win = searchWindow(e->xclient.window);
614         if (win && win->validateClient()) {
615           const Atom action = (Atom) e->xclient.data.l[0];
616           const Atom state[] = { (Atom) e->xclient.data.l[1],
617                                  (Atom) e->xclient.data.l[2] };
618           
619           for (int i = 0; i < 2; ++i) {
620             if (! state[i])
621               continue;
622
623             if ((Atom) e->xclient.data.l[0] == 1) {
624               // ADD
625               if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
626                 win->setModal(True);
627               } else if (state[i] ==
628                          xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
629                 if (win->isMaximizedHoriz()) {
630                   win->maximize(0); // unmaximize
631                   win->maximize(1); // full
632                 } else if (! win->isMaximized()) {
633                   win->maximize(2); // vert
634                 }
635               } else if (state[i] ==
636                          xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
637                 if (win->isMaximizedVert()) {
638                   win->maximize(0); // unmaximize
639                   win->maximize(1); // full
640                 } else if (! win->isMaximized()) {
641                   win->maximize(3); // horiz
642                 }
643               } else if (state[i] ==
644                          xatom->getAtom(XAtom::net_wm_state_shaded)) {
645                 if (! win->isShaded())
646                   win->shade();
647               } else if (state[i] ==
648                          xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
649                 win->setSkipTaskbar(True);
650               } else if (state[i] ==
651                          xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
652                 win->setSkipPager(True);
653               } else if (state[i] ==
654                          xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
655                 win->setFullscreen(True);
656               }
657             } else if (action == 0) {
658               // REMOVE
659               if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
660                 win->setModal(False);
661               } else if (state[i] ==
662                          xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
663                 if (win->isMaximizedFull()) {
664                   win->maximize(0); // unmaximize
665                   win->maximize(3); // horiz
666                 } else if (win->isMaximizedVert()) {
667                   win->maximize(0); // unmaximize
668                 }
669               } else if (state[i] ==
670                          xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
671                 if (win->isMaximizedFull()) {
672                   win->maximize(0); // unmaximize
673                   win->maximize(2); // vert
674                 } else if (win->isMaximizedHoriz()) {
675                   win->maximize(0); // unmaximize
676                 }
677               } else if (state[i] ==
678                          xatom->getAtom(XAtom::net_wm_state_shaded)) {
679                 if (win->isShaded())
680                   win->shade();
681               } else if (state[i] ==
682                          xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
683                 win->setSkipTaskbar(False);
684               } else if (state[i] ==
685                          xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
686                 win->setSkipPager(False);
687               } else if (state[i] ==
688                          xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
689                 win->setFullscreen(False);
690               }
691             } else if (action == 2) {
692               // TOGGLE
693               if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
694                 win->setModal(! win->isModal());
695               } else if (state[i] ==
696                          xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
697                 if (win->isMaximizedFull()) {
698                   win->maximize(0); // unmaximize
699                   win->maximize(3); // horiz
700                 } else if (win->isMaximizedVert()) {
701                   win->maximize(0); // unmaximize
702                 } else if (win->isMaximizedHoriz()) {
703                   win->maximize(0); // unmaximize
704                   win->maximize(1); // full
705                 } else {
706                   win->maximize(2); // vert
707                 }
708               } else if (state[i] ==
709                          xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
710                 if (win->isMaximizedFull()) {
711                   win->maximize(0); // unmaximize
712                   win->maximize(2); // vert
713                 } else if (win->isMaximizedHoriz()) {
714                   win->maximize(0); // unmaximize
715                 } else if (win->isMaximizedVert()) {
716                   win->maximize(0); // unmaximize
717                   win->maximize(1); // full
718                 } else {
719                   win->maximize(3); // horiz
720                 }
721               } else if (state[i] ==
722                          xatom->getAtom(XAtom::net_wm_state_shaded)) {
723                 win->shade();
724               } else if (state[i] ==
725                          xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
726                 win->setSkipTaskbar(! win->skipTaskbar());
727               } else if (state[i] ==
728                          xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
729                 win->setSkipPager(! win->skipPager());
730               } else if (state[i] ==
731                          xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
732                 win->setFullscreen(! win->isFullscreen());
733               }
734             }
735           }
736         }
737       }
738     }
739
740     break;
741   }
742
743   case NoExpose:
744   case ConfigureNotify:
745   case MapNotify:
746     break; // not handled, just ignore
747 */
748   } // switch
749 }
750
751
752 }