1 /*
2 * Oroborus Window Manager
3 *
4 * Copyright (C) 2001 Ken Lynch
5 * Copyright (C) 2002-2005 Stefan Pfetzing
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <X11/Xlib.h>
27 #include <X11/Xmd.h>
28 #include <X11/extensions/shape.h>
29 #include <X11/Xatom.h>
30 #include <X11/xpm.h>
31
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/time.h>
39 #include <sys/select.h>
40
41 #ifdef DEBUG
42 #include <stdio.h>
43 #endif
44
45 #include "client.h"
46 #include "events.h"
47 #include "frame.h"
48 #include "getopt.h"
49 #include "hints.h"
50 #include "i18n.h"
51 #include "keyboard.h"
52 #include "misc.h"
53 #include "oroborus.h"
54 #include "pixmap.h"
55 #include "session.h"
56 #include "workspaces.h"
57
58 #include "globals.h"
59
60 Bool raise_current_window = False;
61
62 void
handleKeyPress(XKeyEvent * ev)63 handleKeyPress (XKeyEvent * ev)
64 {
65 client_t *c;
66 int state, key;
67 XEvent e;
68 XWindowChanges wc;
69
70 #ifdef DEBUG
71 printf ("entering handleKeyEvent\n");
72 #endif
73
74 c = clientGetFocus ();
75 state = ev->state & (Mod1Mask | Mod4Mask | ControlMask | ShiftMask);
76 for (key = 0; key < KEY_ENUM_MAX; key++)
77 if (keys[key].keycode == ev->keycode && keys[key].modifier == state)
78 break;
79
80 if (c)
81 {
82 switch (key)
83 {
84 case KEY_QUIT:
85 quit = True;
86 break;
87 case KEY_MOVE_UP:
88 case KEY_MOVE_DOWN:
89 case KEY_MOVE_LEFT:
90 case KEY_MOVE_RIGHT:
91 clientMove (c, (XEvent *) ev);
92 clientWarpMouse (c);
93 break;
94 case KEY_TOP_LEFT:
95 wc.x = frameLeft (c) + margins[MARGIN_LEFT];
96 wc.y = frameTop (c) + margins[MARGIN_TOP];
97 clientConfigure (c, &wc, CWX | CWY);
98 clientWarpMouse (c);
99 break;
100 case KEY_TOP_RIGHT:
101 wc.x =
102 XDisplayWidth (dpy,
103 screen) - c->width - frameRight (c) -
104 margins[MARGIN_RIGHT];
105 wc.y = frameTop (c) + margins[MARGIN_TOP];
106 clientConfigure (c, &wc, CWX | CWY);
107 clientWarpMouse (c);
108 break;
109 case KEY_BOTTOM_LEFT:
110 wc.x = frameLeft (c) + margins[MARGIN_LEFT];
111 wc.y =
112 XDisplayHeight (dpy,
113 screen) - c->height - frameBottom (c) -
114 margins[MARGIN_BOTTOM];
115 clientConfigure (c, &wc, CWX | CWY);
116 clientWarpMouse (c);
117 break;
118 case KEY_BOTTOM_RIGHT:
119 wc.x =
120 XDisplayWidth (dpy,
121 screen) - c->width - frameRight (c) -
122 margins[MARGIN_RIGHT];
123 wc.y =
124 XDisplayHeight (dpy,
125 screen) - c->height - frameBottom (c) -
126 margins[MARGIN_BOTTOM];
127 clientConfigure (c, &wc, CWX | CWY);
128 clientWarpMouse (c);
129 break;
130 case KEY_RESIZE_UP:
131 case KEY_RESIZE_DOWN:
132 case KEY_RESIZE_LEFT:
133 case KEY_RESIZE_RIGHT:
134 clientResize (c, (XEvent *) ev);
135 clientWarpMouse (c);
136 break;
137 case KEY_CYCLE_WINDOWS:
138 clientCycle (c);
139 break;
140 case KEY_CLOSE_WINDOW:
141 clientClose (c);
142 break;
143 case KEY_HIDE_WINDOW:
144 clientHide (c, True);
145 break;
146 case KEY_TOGGLE_FULLSCREEN_WINDOW:
147 clientToggleFullscreen (c);
148 break;
149 case KEY_MAXIMIZE_WINDOW:
150 clientToggleMaximized (c, WIN_STATE_MAXIMIZED);
151 clientWarpMouse (c);
152 break;
153 case KEY_MAXIMIZE_VERT:
154 clientToggleMaximized (c, WIN_STATE_MAXIMIZED_VERT);
155 clientWarpMouse (c);
156 break;
157 case KEY_MAXIMIZE_HORIZ:
158 clientToggleMaximized (c, WIN_STATE_MAXIMIZED_HORIZ);
159 clientWarpMouse (c);
160 break;
161 case KEY_SHADE_WINDOW:
162 clientToggleShaded (c);
163 break;
164 case KEY_RAISE_WINDOW_LAYER:
165 clientSetLayer (c, c->win_layer + 1);
166 break;
167 case KEY_LOWER_WINDOW_LAYER:
168 clientSetLayer (c, c->win_layer - 1);
169 break;
170 case KEY_NEXT_WORKSPACE:
171 workspaceSwitch (workspace + 1, NULL);
172 clientWarpMouse (clientGetFocus ());
173 break;
174 case KEY_PREV_WORKSPACE:
175 workspaceSwitch (workspace - 1, NULL);
176 clientWarpMouse (clientGetFocus ());
177 break;
178 case KEY_ADD_WORKSPACE:
179 workspaceSetCount (workspace_count + 1);
180 setNetWorkarea (margins, workspace_count);
181 break;
182 case KEY_DEL_WORKSPACE:
183 workspaceSetCount (workspace_count - 1);
184 setNetWorkarea (margins, workspace_count);
185 break;
186 case KEY_STICK_WINDOW:
187 clientToggleSticky (c);
188 break;
189 case KEY_WORKSPACE_1:
190 workspaceSwitch (0, NULL);
191 clientWarpMouse (clientGetFocus ());
192 break;
193 case KEY_WORKSPACE_2:
194 workspaceSwitch (1, NULL);
195 clientWarpMouse (clientGetFocus ());
196 break;
197 case KEY_WORKSPACE_3:
198 workspaceSwitch (2, NULL);
199 clientWarpMouse (clientGetFocus ());
200 break;
201 case KEY_WORKSPACE_4:
202 workspaceSwitch (3, NULL);
203 clientWarpMouse (clientGetFocus ());
204 break;
205 case KEY_WORKSPACE_5:
206 workspaceSwitch (4, NULL);
207 clientWarpMouse (clientGetFocus ());
208 break;
209 case KEY_WORKSPACE_6:
210 workspaceSwitch (5, NULL);
211 clientWarpMouse (clientGetFocus ());
212 break;
213 case KEY_WORKSPACE_7:
214 workspaceSwitch (6, NULL);
215 clientWarpMouse (clientGetFocus ());
216 break;
217 case KEY_WORKSPACE_8:
218 workspaceSwitch (7, NULL);
219 clientWarpMouse (clientGetFocus ());
220 break;
221 case KEY_WORKSPACE_9:
222 workspaceSwitch (8, NULL);
223 clientWarpMouse (clientGetFocus ());
224 break;
225 case KEY_MOVE_NEXT_WORKSPACE:
226 workspaceSwitch (workspace + 1, c);
227 clientWarpMouse (clientGetFocus ());
228 break;
229 case KEY_MOVE_PREV_WORKSPACE:
230 workspaceSwitch (workspace - 1, c);
231 clientWarpMouse (clientGetFocus ());
232 break;
233 case KEY_MOVE_WORKSPACE_1:
234 workspaceSwitch (0, c);
235 clientWarpMouse (clientGetFocus ());
236 break;
237 case KEY_MOVE_WORKSPACE_2:
238 workspaceSwitch (1, c);
239 clientWarpMouse (clientGetFocus ());
240 break;
241 case KEY_MOVE_WORKSPACE_3:
242 workspaceSwitch (2, c);
243 clientWarpMouse (clientGetFocus ());
244 break;
245 case KEY_MOVE_WORKSPACE_4:
246 workspaceSwitch (3, c);
247 clientWarpMouse (clientGetFocus ());
248 break;
249 case KEY_MOVE_WORKSPACE_5:
250 workspaceSwitch (4, c);
251 clientWarpMouse (clientGetFocus ());
252 break;
253 case KEY_MOVE_WORKSPACE_6:
254 workspaceSwitch (5, c);
255 clientWarpMouse (clientGetFocus ());
256 break;
257 case KEY_MOVE_WORKSPACE_7:
258 workspaceSwitch (6, c);
259 clientWarpMouse (clientGetFocus ());
260 break;
261 case KEY_MOVE_WORKSPACE_8:
262 workspaceSwitch (7, c);
263 clientWarpMouse (clientGetFocus ());
264 break;
265 case KEY_MOVE_WORKSPACE_9:
266 workspaceSwitch (8, c);
267 clientWarpMouse (clientGetFocus ());
268 break;
269 }
270 }
271 else
272 {
273 switch (key)
274 {
275 case KEY_QUIT:
276 quit = True;
277 break;
278 case KEY_CYCLE_WINDOWS:
279 if (clients)
280 clientCycle (clients->prev);
281 break;
282 case KEY_NEXT_WORKSPACE:
283 workspaceSwitch (workspace + 1, NULL);
284 clientWarpMouse (clientGetFocus ());
285 break;
286 case KEY_PREV_WORKSPACE:
287 workspaceSwitch (workspace - 1, NULL);
288 clientWarpMouse (clientGetFocus ());
289 break;
290 case KEY_ADD_WORKSPACE:
291 workspaceSetCount (workspace_count + 1);
292 setNetWorkarea (margins, workspace_count);
293 break;
294 case KEY_DEL_WORKSPACE:
295 workspaceSetCount (workspace_count - 1);
296 setNetWorkarea (margins, workspace_count);
297 break;
298 case KEY_WORKSPACE_1:
299 workspaceSwitch (0, NULL);
300 clientWarpMouse (clientGetFocus ());
301 break;
302 case KEY_WORKSPACE_2:
303 workspaceSwitch (1, NULL);
304 clientWarpMouse (clientGetFocus ());
305 break;
306 case KEY_WORKSPACE_3:
307 workspaceSwitch (2, NULL);
308 clientWarpMouse (clientGetFocus ());
309 break;
310 case KEY_WORKSPACE_4:
311 workspaceSwitch (3, NULL);
312 clientWarpMouse (clientGetFocus ());
313 break;
314 case KEY_WORKSPACE_5:
315 workspaceSwitch (4, NULL);
316 clientWarpMouse (clientGetFocus ());
317 break;
318 case KEY_WORKSPACE_6:
319 workspaceSwitch (5, NULL);
320 clientWarpMouse (clientGetFocus ());
321 break;
322 case KEY_WORKSPACE_7:
323 workspaceSwitch (6, NULL);
324 clientWarpMouse (clientGetFocus ());
325 break;
326 case KEY_WORKSPACE_8:
327 workspaceSwitch (7, NULL);
328 clientWarpMouse (clientGetFocus ());
329 break;
330 case KEY_WORKSPACE_9:
331 workspaceSwitch (8, NULL);
332 clientWarpMouse (clientGetFocus ());
333 break;
334 }
335 }
336
337 while (XCheckTypedEvent (dpy, EnterNotify, &e));
338 }
339
340 void
handleButtonPress(XButtonEvent * ev)341 handleButtonPress (XButtonEvent * ev)
342 {
343 client_t *c;
344 Window win;
345 int state, replay = False;
346 static Time last_button_time;
347
348 #ifdef DEBUG
349 printf ("entering handleButtonPress\n");
350 #endif
351
352 while (XCheckTypedEvent (dpy, ButtonPress, (XEvent *) ev));
353
354 state = ev->state & (Mod1Mask | Mod4Mask | ShiftMask | ControlMask);
355
356 c = clientGetFromWindow (ev->window, FRAME);
357 if (c)
358 {
359 state = ev->state & (Mod1Mask | Mod4Mask | ShiftMask | ControlMask);
360 win = getMouseWindow (dpy, c->frame);
361
362 clientSetFocus (c, True);
363
364 if (win == c->buttons[HIDE_BUTTON] ||
365 win == c->buttons[CLOSE_BUTTON] ||
366 win == c->buttons[MAXIMIZE_BUTTON] ||
367 win == c->buttons[SHADE_BUTTON])
368 {
369 clientRaise (c);
370 clientButtonPress (c, win, ev);
371 }
372 else if (((win == c->title || win == c->sides[SIDE_BOTTOM] ||
373 win == c->sides[SIDE_LEFT] || win == c->sides[SIDE_RIGHT]) &&
374 ev->button == Button1 && state == 0) || (ev->button == Button1
375 && state ==
376 keys[KEY_WINDOW_OPS].
377 modifier))
378 {
379 clientRaise (c);
380 if (ev->time - last_button_time <= 250 && last_button_time != 0)
381 {
382 switch (double_click_action)
383 {
384 case ACTION_MAXIMIZE:
385 clientToggleMaximized (c, WIN_STATE_MAXIMIZED);
386 break;
387 case ACTION_SHADE:
388 clientToggleShaded (c);
389 break;
390 case ACTION_HIDE:
391 clientHide (c, True);
392 break;
393 }
394 last_button_time = 0;
395 }
396 else
397 {
398 clientMove (c, (XEvent *) ev);
399 last_button_time = ev->time;
400 }
401 }
402 else if ((win == c->corners[CORNER_TOP_LEFT] ||
403 win == c->corners[CORNER_TOP_RIGHT] ||
404 win == c->corners[CORNER_BOTTOM_LEFT] ||
405 win == c->corners[CORNER_BOTTOM_RIGHT]) &&
406 ev->button == Button1 && state == 0)
407 {
408 clientRaise (c);
409 clientResize (c, (XEvent *) ev);
410 }
411 else if (win != c->window && ev->button == Button2 && state == 0
412 && !typeDesktop (c->window))
413 {
414 clientRaise (c);
415 clientToggleSticky (c);
416 }
417 else if (ev->button == Button2
418 && state == keys[KEY_WINDOW_OPS].modifier
419 && !typeDesktop (c->window))
420 {
421 clientRaise (c);
422 clientResize (c, (XEvent *) ev);
423 }
424 else if (((win != c->window && ev->button == Button3 && state == 0) ||
425 (ev->button == Button3
426 && state == keys[KEY_WINDOW_OPS].modifier))
427 && !typeDesktop (c->window))
428 clientLower (c);
429 else if (win != c->window && ev->button == Button1 && state == Mod1Mask)
430 clientSetLayer (c, c->win_layer + 1);
431 else if (win != c->window && ev->button == Button3 && state == Mod1Mask)
432 clientSetLayer (c, c->win_layer - 1);
433 else
434 {
435 if (raise_on_click)
436 clientRaise (c);
437 if (win == c->window)
438 replay = True;
439 }
440
441 if (replay)
442 XAllowEvents (dpy, ReplayPointer, CurrentTime);
443 else
444 XAllowEvents (dpy, SyncPointer, CurrentTime);
445
446 switch_timer(False);
447 }
448 else
449 {
450 XUngrabPointer (dpy, CurrentTime);
451 XSendEvent (dpy, gnome_win, False, SubstructureNotifyMask,
452 (XEvent *) ev);
453 }
454 }
455
456 void
handleButtonRelease(XButtonEvent * ev)457 handleButtonRelease (XButtonEvent * ev)
458 {
459 #ifdef DEBUG
460 printf ("entering handleButtonRelease\n");
461 #endif
462
463 XSendEvent (dpy, gnome_win, False, SubstructureNotifyMask, (XEvent *) ev);
464 }
465
466 void
handleDestroyNotify(XDestroyWindowEvent * ev)467 handleDestroyNotify (XDestroyWindowEvent * ev)
468 {
469 client_t *c;
470
471 #ifdef DEBUG
472 printf ("entering handleDestroyNotify\n");
473 #endif
474
475 c = clientGetFromWindow (ev->window, WINDOW);
476 if (c)
477 {
478 clientUnframe (c, False);
479 if (clients)
480 {
481 c = clientGetTopMostShaded (WIN_LAYER_NORMAL, True);
482 if (!c)
483 c = clientGetTopMost (WIN_LAYER_NORMAL);
484
485 clientSetFocus (c, True);
486 }
487 else
488 clientSetFocus (NULL, True);
489 }
490 }
491
492 void
handleUnmapNotify(XUnmapEvent * ev)493 handleUnmapNotify (XUnmapEvent * ev)
494 {
495 client_t *c;
496
497 #ifdef DEBUG
498 printf ("entering handleUnmapNotify\n");
499 #endif
500
501 c = clientGetFromWindow (ev->window, WINDOW);
502 if (c)
503 {
504 if (c->ignore_unmap)
505 c->ignore_unmap--;
506 else
507 {
508 clientUnframe (c, False);
509 if (clients)
510 {
511 c = clientGetTopMostShaded (WIN_LAYER_NORMAL, True);
512 if (!c)
513 c = clientGetTopMost (WIN_LAYER_NORMAL);
514 clientSetFocus (c, True);
515 }
516 else
517 clientSetFocus (NULL, True);
518 }
519 }
520 }
521
522 void
handleMapRequest(XMapRequestEvent * ev)523 handleMapRequest (XMapRequestEvent * ev)
524 {
525 client_t *c;
526
527 #ifdef DEBUG
528 printf ("entering handleMapRequest\n");
529 #endif
530
531 c = clientGetFromWindow (ev->window, WINDOW);
532 if (c)
533 clientShow (c, True);
534 else
535 clientFrame (ev->window);
536 }
537
538 void
handleConfigureRequest(XConfigureRequestEvent * ev)539 handleConfigureRequest (XConfigureRequestEvent * ev)
540 {
541 client_t *c;
542 XWindowChanges wc;
543
544 #ifdef DEBUG
545 printf ("entering handleConfigureRequest\n");
546 #endif
547
548 wc.x = ev->x;
549 wc.y = ev->y;
550 wc.width = ev->width;
551 wc.height = ev->height;
552 wc.sibling = ev->above;
553 wc.stack_mode = ev->detail;
554 wc.border_width = ev->border_width;
555
556 c = clientGetFromWindow (ev->window, WINDOW);
557
558 if (c)
559 {
560 if (! (c->above || c->was_above))
561 {
562 wc.x += frameLeft(c);
563 wc.y += frameTop(c);
564 }
565 clientConfigure (c, &wc, ev->value_mask);
566 }
567 else
568 XConfigureWindow (dpy, ev->window, ev->value_mask, &wc);
569 }
570
571 void
handleEnterNotify(XCrossingEvent * ev)572 handleEnterNotify (XCrossingEvent * ev)
573 {
574 client_t *c;
575
576 #ifdef DEBUG
577 printf ("entering handleEnterNotify\n");
578 #endif
579
580 while (XCheckTypedEvent (dpy, EnterNotify, (XEvent *) ev));
581
582 c = clientGetFromWindow (ev->window, FRAME);
583 if (c && !click_to_focus)
584 clientSetFocus (c, True);
585
586 }
587
588 void
handleFocusIn(XFocusChangeEvent * ev)589 handleFocusIn (XFocusChangeEvent * ev)
590 {
591 client_t *c;
592
593 #ifdef DEBUG
594 printf ("entering handleFocusIn\n");
595 #endif
596
597 c = clientGetFromWindow (ev->window, WINDOW);
598 if (c)
599 frameDraw (c);
600 else if (clients)
601 clientSetFocus (clientGetNext (clients->prev, 0), True);
602 else
603 clientSetFocus (NULL, True);
604
605 if (raise_on_focus)
606 switch_timer(True);
607 }
608
609 void
handleFocusOut(XFocusChangeEvent * ev)610 handleFocusOut (XFocusChangeEvent * ev)
611 {
612 client_t *c;
613
614 #ifdef DEBUG
615 printf ("entering handleFocusOut\n");
616 #endif
617
618 c = clientGetFromWindow (ev->window, WINDOW);
619 if (c)
620 frameDraw (c);
621 }
622
623 void
handlePropertyNotify(XPropertyEvent * ev)624 handlePropertyNotify (XPropertyEvent * ev)
625 {
626 client_t *c;
627 long dummy;
628
629 #ifdef DEBUG
630 printf ("entering handlePropertyNotify\n");
631 #endif
632
633 c = clientGetFromWindow (ev->window, WINDOW);
634 if (c)
635 {
636 if (ev->atom == XA_WM_NORMAL_HINTS)
637 XGetWMNormalHints (dpy, c->window, c->size, &dummy);
638 else if (ev->atom == XA_WM_NAME)
639 {
640 if (c->name)
641 free (c->name);
642 getWindowName (dpy, c->window, &c->name);
643 frameDraw (c);
644 }
645 else if (ev->atom == win_hints)
646 getGnomeHint (c->window, win_hints, &c->win_hints);
647 else if (ev->atom == net_atoms[NET_WM_STRUT])
648 {
649 delNetWMStrut (margins, c->margins);
650 getNetWMStrut (c->window, margins, c->margins);
651 }
652 else if (ev->atom == win_layer)
653 {
654 getGnomeHint (c->window, win_layer, &dummy);
655 clientSetLayer (c, dummy);
656 }
657 else if (ev->atom == win_workspace)
658 {
659 getGnomeHint (c->window, win_workspace, &dummy);
660 clientSetWorkspace (c, dummy);
661 }
662 }
663 else
664 {
665 if (ev->atom == win_workspace_count)
666 {
667 getGnomeHint (root, win_workspace_count, &dummy);
668 workspaceSetCount (dummy);
669 setNetWorkarea (margins, workspace_count);
670 }
671 else if (ev->atom == gnome_panel_desktop_area)
672 {
673 getGnomeDesktopMargins (margins);
674 setNetWorkarea (margins, workspace_count);
675 }
676 }
677 }
678
679 void
handleClientMessage(XClientMessageEvent * ev)680 handleClientMessage (XClientMessageEvent * ev)
681 {
682 client_t *c;
683
684 #ifdef DEBUG
685 printf ("entering handleClientMessage\n");
686 #endif
687
688 c = clientGetFromWindow (ev->window, WINDOW);
689 if (c)
690 {
691 if (ev->message_type == wm_change_state && ev->format == 32 &&
692 ev->data.l[0] == IconicState)
693 clientHide (c, True);
694 else if (ev->message_type == win_layer && ev->format == 32)
695 {
696 setGnomeHint (c->window, ev->data.l[0], win_hints);
697 clientSetLayer (c, ev->data.l[0]);
698 if (ev->data.l[0] == 6)
699 clientToggleAbove (c);
700 clientRaise (c);
701 }
702 else if (ev->message_type == win_state && ev->format == 32)
703 clientSetState (c, ev->data.l[0], ev->data.l[1]);
704 else
705 if ((ev->message_type == win_workspace
706 || ev->message_type == net_atoms[NET_WM_DESKTOP])
707 && ev->format == 32)
708 clientSetWorkspace (c, ev->data.l[0]);
709 else if (ev->message_type == net_atoms[NET_ACTIVE_WINDOW]
710 && ev->format == 32)
711 {
712 if (getWMState (c->window) == IconicState)
713 clientShow (c, False);
714 clientSetFocus (c, True);
715 clientRaise (c);
716 setWMState (c->window, NormalState);
717 }
718 else if (ev->message_type == net_atoms[NET_CLOSE_WINDOW]
719 && ev->format == 32)
720 clientClose (c);
721 else if (ev->message_type == net_atoms[NET_WM_STATE]
722 && ev->format == 32)
723 {
724 switch (ev->data.l[0])
725 {
726 case NET_WM_STATE_ADD:
727 case NET_WM_STATE_REMOVE:
728 case NET_WM_STATE_TOGGLE:
729 if (ev->data.l[1] == net_atoms[NET_WM_STATE_ABOVE]
730 || ev->data.l[2] == net_atoms[NET_WM_STATE_ABOVE])
731 clientToggleAbove (c);
732 if (ev->data.l[1] == net_atoms[NET_WM_STATE_FULLSCREEN]
733 || ev->data.l[2] == net_atoms[NET_WM_STATE_FULLSCREEN])
734 clientToggleFullscreen(c);
735 break;
736 }
737 }
738 }
739 else
740 {
741 if ((ev->message_type == win_workspace
742 || ev->message_type == net_atoms[NET_WM_DESKTOP]
743 || ev->message_type == net_atoms[NET_CURRENT_DESKTOP])
744 && ev->format == 32)
745 workspaceSwitch (ev->data.l[0], NULL);
746 else
747 if ((ev->message_type == win_workspace_count
748 || ev->message_type == net_atoms[NET_NUMBER_OF_DESKTOPS])
749 && ev->format == 32)
750 {
751 workspaceSetCount (ev->data.l[0]);
752 setNetWorkarea (margins, workspace_count);
753 }
754 }
755 }
756
757 void
handleShape(XShapeEvent * ev)758 handleShape (XShapeEvent * ev)
759 {
760 client_t *c;
761
762 #ifdef DEBUG
763 printf ("entering handleShape\n");
764 #endif
765
766 c = clientGetFromWindow (ev->window, WINDOW);
767 if (c)
768 frameDraw (c);
769 }
770
771 void
handleEvent(XEvent * ev)772 handleEvent (XEvent * ev)
773 {
774 #ifdef DEBUG
775 printf ("entering handleEvent\n");
776 #endif
777
778 switch (ev->type)
779 {
780 case KeyPress:
781 #ifdef DEBUG
782 printf ("KeyPress\n");
783 #endif
784 handleKeyPress ((XKeyEvent *) ev);
785 break;
786 case ButtonPress:
787 #ifdef DEBUG
788 printf ("ButtonPress\n");
789 #endif
790 handleButtonPress ((XButtonEvent *) ev);
791 break;
792 case ButtonRelease:
793 #ifdef DEBUG
794 printf ("ButtonRelease\n");
795 #endif
796 handleButtonRelease ((XButtonEvent *) ev);
797 break;
798 case DestroyNotify:
799 #ifdef DEBUG
800 printf ("DestroyNotify\n");
801 #endif
802 handleDestroyNotify ((XDestroyWindowEvent *) ev);
803 break;
804 case UnmapNotify:
805 #ifdef DEBUG
806 printf ("UnmapNotify\n");
807 #endif
808 handleUnmapNotify ((XUnmapEvent *) ev);
809 break;
810 case MapRequest:
811 #ifdef DEBUG
812 printf ("MapRequest\n");
813 #endif
814 handleMapRequest ((XMapRequestEvent *) ev);
815 break;
816 case ConfigureRequest:
817 #ifdef DEBUG
818 printf ("ConfigureRequest\n");
819 #endif
820 handleConfigureRequest ((XConfigureRequestEvent *) ev);
821 break;
822 case EnterNotify:
823 #ifdef DEBUG
824 printf ("EnterNotify\n");
825 #endif
826 handleEnterNotify ((XCrossingEvent *) ev);
827 break;
828 case FocusIn:
829 #ifdef DEBUG
830 printf ("FocusIn\n");
831 #endif
832 handleFocusIn ((XFocusChangeEvent *) ev);
833 break;
834 case FocusOut:
835 #ifdef DEBUG
836 printf ("FocusOut\n");
837 #endif
838 handleFocusOut ((XFocusChangeEvent *) ev);
839 break;
840 case PropertyNotify:
841 #ifdef DEBUG
842 printf ("PropertyNotify\n");
843 #endif
844 handlePropertyNotify ((XPropertyEvent *) ev);
845 break;
846 case ClientMessage:
847 #ifdef DEBUG
848 printf ("clientMessage\n");
849 #endif
850 handleClientMessage ((XClientMessageEvent *) ev);
851 break;
852 default:
853 #ifdef DEBUG
854 printf ("default\n");
855 #endif
856 if (shape && ev->type == shape_event)
857 handleShape ((XShapeEvent *) ev);
858 }
859 }
860
861 void
eventLoop()862 eventLoop ()
863 {
864 fd_set readset;
865 int x_fd;
866 XEvent ev;
867 int nfds;
868
869 #ifdef DEBUG
870 printf ("entering eventLoop\n");
871 #endif
872
873 /* first get the X11 fd */
874 x_fd = XConnectionNumber (dpy);
875
876 while (1)
877 {
878 /* then zero the readset and add the x_fd to it */
879 FD_ZERO (&readset);
880 FD_SET (x_fd, &readset);
881
882 /* if the ice_fd exists, add it to the readset too. */
883 if (ice_fd != -1)
884 FD_SET (ice_fd, &readset);
885
886 /* compute the number of the highest fd for the select call */
887 nfds = (x_fd > ice_fd) ? x_fd+1 : ice_fd+1;
888
889 /* did we catch a -1 (interrupted / error) in the select call? */
890 INT: if (-1 == select (nfds, &readset, NULL, NULL, NULL))
891 {
892 if (errno == EINTR)
893 {
894 /* do we need to reload oroborus? */
895 if (reload)
896 {
897 cleanUp ();
898 #ifdef DEBUG
899 printf ("executing: %s\n", progname);
900 #endif
901 /* exec oroborus itself */
902 execvp (progname, stat_argv);
903 }
904
905 /* do we need to raise the current window?
906 * raise_current_window is set in the SIGALRM handler.
907 */
908 if (raise_current_window)
909 {
910 client_t *c = clientGetFocus();
911
912 raise_current_window = False;
913 /* is there a client, then raise it */
914 if (c)
915 {
916 #ifdef DEBUG
917 printf ("raising client (%#lx)\n", c->window);
918 #endif
919 clientRaise (c);
920 XFlush(dpy);
921 }
922 }
923
924 /* shall we quit? */
925 if (quit)
926 return;
927
928 /* EINTR means, we just can re-execute the select call.
929 * Sorry, but in this case just the best is a goto.
930 */
931 goto INT;
932 }
933
934 /* now comes the case, select fails, and errno is not EINTR. */
935 else
936 return;
937
938 }
939 else
940 {
941 /* now lets check the fd's */
942 if (FD_ISSET (x_fd, &readset))
943 /* process all pending requests */
944 while (XPending (dpy))
945 {
946 XNextEvent (dpy, &ev);
947 handleEvent (&ev);
948 }
949 else if (FD_ISSET (ice_fd, &readset))
950 /* process the ice messages */
951 process_ice_msgs ();
952 }
953
954 }
955
956 #ifdef DEBUG
957 printf ("leaving eventLoop\n");
958 #endif
959 }
960
961 void
switch_timer(Bool enable)962 switch_timer (Bool enable)
963 {
964 struct itimerval itimer;
965
966 #ifdef DEBUG
967 if (enable)
968 printf ("TIMER: enabling\n");
969 else
970 printf ("TIMER: disabling\n");
971 #endif
972
973 /* we don't need an interval */
974 itimer.it_interval.tv_usec = 0;
975 itimer.it_interval.tv_sec = 0;
976
977 if (enable)
978 /* insert the timer value here */
979 itimer.it_value.tv_usec = raise_delay*1000;
980 else
981 itimer.it_value.tv_usec = 0;
982
983 itimer.it_value.tv_sec = 0;
984
985 setitimer (ITIMER_REAL, &itimer, NULL);
986 }
987
988 /***This must remain at the end of the file.***********************************************
989 * vi:set sw=2 cindent cinoptions={1s,>2s,^-1s,n-1s foldmethod=marker foldmarker=���,���: *
990 * arch-tag: event handling for oroborus-wm *
991 ******************************************************************************************/
992