]> Dogcows Code - chaz/openbox/blob - src/blackbox.cc
WE DONT USE BASE DISPLAY FOR ANYTHING ANY MORE!!@^!*@*!! YAY
[chaz/openbox] / src / blackbox.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 extern "C" {
8 #include <X11/Xlib.h>
9 #include <X11/Xutil.h>
10 #include <X11/Xatom.h>
11 #include <X11/cursorfont.h>
12 #include <X11/keysym.h>
13
14 #ifdef SHAPE
15 #include <X11/extensions/shape.h>
16 #endif // SHAPE
17
18 #ifdef HAVE_STDIO_H
19 # include <stdio.h>
20 #endif // HAVE_STDIO_H
21
22 #ifdef HAVE_STDLIB_H
23 # include <stdlib.h>
24 #endif // HAVE_STDLIB_H
25
26 #ifdef HAVE_STRING_H
27 # include <string.h>
28 #endif // HAVE_STRING_H
29
30 #ifdef HAVE_UNISTD_H
31 # include <sys/types.h>
32 # include <unistd.h>
33 #endif // HAVE_UNISTD_H
34
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif // HAVE_SYS_PARAM_H
38
39 #ifdef HAVE_SYS_SELECT_H
40 # include <sys/select.h>
41 #endif // HAVE_SYS_SELECT_H
42
43 #ifdef HAVE_SIGNAL_H
44 # include <signal.h>
45 #endif // HAVE_SIGNAL_H
46
47 #ifdef HAVE_SYS_SIGNAL_H
48 # include <sys/signal.h>
49 #endif // HAVE_SYS_SIGNAL_H
50
51 #ifdef HAVE_SYS_STAT_H
52 # include <sys/types.h>
53 # include <sys/stat.h>
54 #endif // HAVE_SYS_STAT_H
55
56 #ifdef TIME_WITH_SYS_TIME
57 # include <sys/time.h>
58 # include <time.h>
59 #else // !TIME_WITH_SYS_TIME
60 # ifdef HAVE_SYS_TIME_H
61 # include <sys/time.h>
62 # else // !HAVE_SYS_TIME_H
63 # include <time.h>
64 # endif // HAVE_SYS_TIME_H
65 #endif // TIME_WITH_SYS_TIME
66
67 #ifdef HAVE_LIBGEN_H
68 # include <libgen.h>
69 #endif // HAVE_LIBGEN_H
70 }
71
72 #include <assert.h>
73
74 #include <algorithm>
75 #include <string>
76 using std::string;
77
78 #include "blackbox.hh"
79 #include "otk/gccache.hh"
80 #include "otk/image.hh"
81 #include "otk/assassin.hh"
82 #include "screen.hh"
83 #include "util.hh"
84 #include "window.hh"
85 #include "workspace.hh"
86 #include "xatom.hh"
87
88 namespace ob {
89
90 Blackbox *blackbox;
91
92
93 Blackbox::Blackbox(int argc, char **m_argv, char *rc)
94 : Openbox(argc, m_argv) {
95
96 if (! XSupportsLocale())
97 fprintf(stderr, "X server does not support locale\n");
98
99 if (XSetLocaleModifiers("") == NULL)
100 fprintf(stderr, "cannot set locale modifiers\n");
101
102 ob::blackbox = this;
103 argv = m_argv;
104
105 // try to make sure the ~/.openbox directory exists
106 mkdir(expandTilde("~/.openbox").c_str(), S_IREAD | S_IWRITE | S_IEXEC |
107 S_IRGRP | S_IWGRP | S_IXGRP |
108 S_IROTH | S_IWOTH | S_IXOTH);
109
110 if (! rc) rc = "~/.openbox/rc";
111 rc_file = expandTilde(rc);
112 config.setFile(rc_file);
113
114 no_focus = False;
115
116 resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0;
117
118 active_screen = 0;
119 focused_window = changing_window = (BlackboxWindow *) 0;
120
121 load_rc();
122
123 xatom = new XAtom(otk::OBDisplay::display);
124
125 cursor.session = XCreateFontCursor(otk::OBDisplay::display, XC_left_ptr);
126 cursor.move = XCreateFontCursor(otk::OBDisplay::display, XC_fleur);
127 cursor.ll_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ll_angle);
128 cursor.lr_angle = XCreateFontCursor(otk::OBDisplay::display, XC_lr_angle);
129 cursor.ul_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ul_angle);
130 cursor.ur_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ur_angle);
131
132 for (int i = 0; i < ScreenCount(otk::OBDisplay::display); i++) {
133 BScreen *screen = new BScreen(this, i);
134
135 if (! screen->isScreenManaged()) {
136 delete screen;
137 continue;
138 }
139
140 screenList.push_back(screen);
141 }
142
143 if (screenList.empty()) {
144 fprintf(stderr,
145 "Blackbox::Blackbox: no managable screens found, aborting.\n");
146 ::exit(3);
147 }
148
149 // save current settings and default values
150 save_rc();
151
152 // set the screen with mouse to the first managed screen
153 active_screen = screenList.front();
154 setFocusedWindow(0);
155
156 XSynchronize(otk::OBDisplay::display, False);
157 XSync(otk::OBDisplay::display, False);
158
159 reconfigure_wait = False;
160
161 timer = new BTimer(this, this);
162 timer->setTimeout(0l);
163 }
164
165
166 Blackbox::~Blackbox(void) {
167 std::for_each(screenList.begin(), screenList.end(), otk::PointerAssassin());
168
169 delete xatom;
170
171 delete timer;
172 }
173
174
175 void Blackbox::process_event(XEvent *e) {
176 switch (e->type) {
177 case ButtonPress: {
178 // strip the lock key modifiers
179 //e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
180
181 last_time = e->xbutton.time;
182
183 BlackboxWindow *win = (BlackboxWindow *) 0;
184 BScreen *scrn = (BScreen *) 0;
185
186 if ((win = searchWindow(e->xbutton.window))) {
187 win->buttonPressEvent(&e->xbutton);
188
189 /* XXX: is this sane on low colour desktops? */
190 if (e->xbutton.button == 1)
191 win->installColormap(True);
192 } else if ((scrn = searchScreen(e->xbutton.window))) {
193 scrn->buttonPressEvent(&e->xbutton);
194 if (active_screen != scrn) {
195 active_screen = scrn;
196 // first, set no focus window on the old screen
197 setFocusedWindow(0);
198 // and move focus to this screen
199 setFocusedWindow(0);
200 }
201 }
202 break;
203 }
204
205 case ButtonRelease: {
206 // strip the lock key modifiers
207 //e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
208
209 last_time = e->xbutton.time;
210
211 BlackboxWindow *win = (BlackboxWindow *) 0;
212
213 if ((win = searchWindow(e->xbutton.window)))
214 win->buttonReleaseEvent(&e->xbutton);
215
216 break;
217 }
218
219 case ConfigureRequest: {
220 BlackboxWindow *win = (BlackboxWindow *) 0;
221
222 if ((win = searchWindow(e->xconfigurerequest.window))) {
223 win->configureRequestEvent(&e->xconfigurerequest);
224 } else {
225 if (validateWindow(e->xconfigurerequest.window)) {
226 XWindowChanges xwc;
227
228 xwc.x = e->xconfigurerequest.x;
229 xwc.y = e->xconfigurerequest.y;
230 xwc.width = e->xconfigurerequest.width;
231 xwc.height = e->xconfigurerequest.height;
232 xwc.border_width = e->xconfigurerequest.border_width;
233 xwc.sibling = e->xconfigurerequest.above;
234 xwc.stack_mode = e->xconfigurerequest.detail;
235
236 XConfigureWindow(otk::OBDisplay::display, e->xconfigurerequest.window,
237 e->xconfigurerequest.value_mask, &xwc);
238 }
239 }
240
241 break;
242 }
243
244 case MapRequest: {
245 #ifdef DEBUG
246 fprintf(stderr, "Blackbox::process_event(): MapRequest for 0x%lx\n",
247 e->xmaprequest.window);
248 #endif // DEBUG
249
250 BlackboxWindow *win = searchWindow(e->xmaprequest.window);
251
252 if (win) {
253 bool focus = False;
254 if (win->isIconic()) {
255 win->deiconify();
256 focus = True;
257 }
258 if (win->isShaded()) {
259 win->shade();
260 focus = True;
261 }
262
263 if (focus && (win->isTransient() || win->getScreen()->doFocusNew()) &&
264 win->isVisible())
265 win->setInputFocus();
266 } else {
267 BScreen *screen = searchScreen(e->xmaprequest.parent);
268
269 if (! screen) {
270 /*
271 we got a map request for a window who's parent isn't root. this
272 can happen in only one circumstance:
273
274 a client window unmapped a managed window, and then remapped it
275 somewhere between unmapping the client window and reparenting it
276 to root.
277
278 regardless of how it happens, we need to find the screen that
279 the window is on
280 */
281 XWindowAttributes wattrib;
282 if (! XGetWindowAttributes(otk::OBDisplay::display, e->xmaprequest.window,
283 &wattrib)) {
284 // failed to get the window attributes, perhaps the window has
285 // now been destroyed?
286 break;
287 }
288
289 screen = searchScreen(wattrib.root);
290 assert(screen != 0); // this should never happen
291 }
292
293 screen->manageWindow(e->xmaprequest.window);
294 }
295
296 break;
297 }
298
299 case UnmapNotify: {
300 BlackboxWindow *win = (BlackboxWindow *) 0;
301 BScreen *screen = (BScreen *) 0;
302
303 if ((win = searchWindow(e->xunmap.window))) {
304 win->unmapNotifyEvent(&e->xunmap);
305 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
306 screen->removeSystrayWindow(e->xunmap.window);
307 }
308
309 break;
310 }
311
312 case DestroyNotify: {
313 BlackboxWindow *win = (BlackboxWindow *) 0;
314 BScreen *screen = (BScreen *) 0;
315 BWindowGroup *group = (BWindowGroup *) 0;
316
317 if ((win = searchWindow(e->xdestroywindow.window))) {
318 win->destroyNotifyEvent(&e->xdestroywindow);
319 } else if ((group = searchGroup(e->xdestroywindow.window))) {
320 delete group;
321 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
322 screen->removeSystrayWindow(e->xunmap.window);
323 }
324
325 break;
326 }
327
328 case ReparentNotify: {
329 /*
330 this event is quite rare and is usually handled in unmapNotify
331 however, if the window is unmapped when the reparent event occurs
332 the window manager never sees it because an unmap event is not sent
333 to an already unmapped window.
334 */
335 BlackboxWindow *win = searchWindow(e->xreparent.window);
336 if (win)
337 win->reparentNotifyEvent(&e->xreparent);
338 break;
339 }
340
341 case MotionNotify: {
342 // motion notify compression...
343 XEvent realevent;
344 unsigned int i = 0;
345 while (XCheckTypedWindowEvent(otk::OBDisplay::display, e->xmotion.window,
346 MotionNotify, &realevent)) {
347 i++;
348 }
349
350 // if we have compressed some motion events, use the last one
351 if ( i > 0 )
352 e = &realevent;
353
354 // the pointer is on the wrong screen
355 if (! e->xmotion.same_screen)
356 break;
357
358 // strip the lock key modifiers
359 //e->xmotion.state &= ~(NumLockMask | ScrollLockMask | LockMask);
360
361 last_time = e->xmotion.time;
362
363 BlackboxWindow *win = (BlackboxWindow *) 0;
364
365 if ((win = searchWindow(e->xmotion.window)))
366 win->motionNotifyEvent(&e->xmotion);
367
368 break;
369 }
370
371 case PropertyNotify: {
372 last_time = e->xproperty.time;
373
374 BlackboxWindow *win = (BlackboxWindow *) 0;
375 BScreen *screen = (BScreen *) 0;
376
377 if ((win = searchWindow(e->xproperty.window)))
378 win->propertyNotifyEvent(&e->xproperty);
379 else if ((screen = searchScreen(e->xproperty.window)))
380 screen->propertyNotifyEvent(&e->xproperty);
381 break;
382 }
383
384 case EnterNotify: {
385 last_time = e->xcrossing.time;
386
387 BScreen *screen = (BScreen *) 0;
388 BlackboxWindow *win = (BlackboxWindow *) 0;
389
390 if (e->xcrossing.mode == NotifyGrab) break;
391
392 if ((e->xcrossing.window == e->xcrossing.root) &&
393 (screen = searchScreen(e->xcrossing.window))) {
394 screen->getImageControl()->installRootColormap();
395 } else if ((win = searchWindow(e->xcrossing.window))) {
396 if (! no_focus)
397 win->enterNotifyEvent(&e->xcrossing);
398 }
399 break;
400 }
401
402 case LeaveNotify: {
403 last_time = e->xcrossing.time;
404
405 BlackboxWindow *win = (BlackboxWindow *) 0;
406
407 if ((win = searchWindow(e->xcrossing.window)))
408 win->leaveNotifyEvent(&e->xcrossing);
409 break;
410 }
411
412 case Expose: {
413 // compress expose events
414 XEvent realevent;
415 unsigned int i = 0;
416 int ex1, ey1, ex2, ey2;
417 ex1 = e->xexpose.x;
418 ey1 = e->xexpose.y;
419 ex2 = ex1 + e->xexpose.width - 1;
420 ey2 = ey1 + e->xexpose.height - 1;
421 while (XCheckTypedWindowEvent(otk::OBDisplay::display, e->xexpose.window,
422 Expose, &realevent)) {
423 i++;
424
425 // merge expose area
426 ex1 = std::min(realevent.xexpose.x, ex1);
427 ey1 = std::min(realevent.xexpose.y, ey1);
428 ex2 = std::max(realevent.xexpose.x + realevent.xexpose.width - 1, ex2);
429 ey2 = std::max(realevent.xexpose.y + realevent.xexpose.height - 1, ey2);
430 }
431 if ( i > 0 )
432 e = &realevent;
433
434 // use the merged area
435 e->xexpose.x = ex1;
436 e->xexpose.y = ey1;
437 e->xexpose.width = ex2 - ex1 + 1;
438 e->xexpose.height = ey2 - ey1 + 1;
439
440 BlackboxWindow *win = (BlackboxWindow *) 0;
441
442 if ((win = searchWindow(e->xexpose.window)))
443 win->exposeEvent(&e->xexpose);
444
445 break;
446 }
447
448 case KeyPress: {
449 break;
450 }
451
452 case ColormapNotify: {
453 BScreen *screen = searchScreen(e->xcolormap.window);
454
455 if (screen)
456 screen->setRootColormapInstalled((e->xcolormap.state ==
457 ColormapInstalled) ? True : False);
458
459 break;
460 }
461
462 case FocusIn: {
463 if (e->xfocus.detail != NotifyNonlinear &&
464 e->xfocus.detail != NotifyAncestor) {
465 /*
466 don't process FocusIns when:
467 1. the new focus window isn't an ancestor or inferior of the old
468 focus window (NotifyNonlinear)
469 make sure to allow the FocusIn when the old focus window was an
470 ancestor but didn't have a parent, such as root (NotifyAncestor)
471 */
472 break;
473 }
474
475 BlackboxWindow *win = searchWindow(e->xfocus.window);
476 if (win) {
477 if (! win->isFocused())
478 win->setFocusFlag(True);
479
480 /*
481 set the event window to None. when the FocusOut event handler calls
482 this function recursively, it uses this as an indication that focus
483 has moved to a known window.
484 */
485 e->xfocus.window = None;
486
487 no_focus = False; // focusing is back on
488 }
489
490 break;
491 }
492
493 case FocusOut: {
494 if (e->xfocus.detail != NotifyNonlinear) {
495 /*
496 don't process FocusOuts when:
497 2. the new focus window isn't an ancestor or inferior of the old
498 focus window (NotifyNonlinear)
499 */
500 break;
501 }
502
503 BlackboxWindow *win = searchWindow(e->xfocus.window);
504 if (win && win->isFocused()) {
505 /*
506 before we mark "win" as unfocused, we need to verify that focus is
507 going to a known location, is in a known location, or set focus
508 to a known location.
509 */
510
511 XEvent event;
512 // don't check the current focus if FocusOut was generated during a grab
513 bool check_focus = (e->xfocus.mode == NotifyNormal);
514
515 /*
516 First, check if there is a pending FocusIn event waiting. if there
517 is, process it and determine if focus has moved to another window
518 (the FocusIn event handler sets the window in the event
519 structure to None to indicate this).
520 */
521 if (XCheckTypedEvent(otk::OBDisplay::display, FocusIn, &event)) {
522
523 process_event(&event);
524 if (event.xfocus.window == None) {
525 // focus has moved
526 check_focus = False;
527 }
528 }
529
530 if (check_focus) {
531 /*
532 Second, we query the X server for the current input focus.
533 to make sure that we keep a consistent state.
534 */
535 BlackboxWindow *focus;
536 Window w;
537 int revert;
538 XGetInputFocus(otk::OBDisplay::display, &w, &revert);
539 focus = searchWindow(w);
540 if (focus) {
541 /*
542 focus got from "win" to "focus" under some very strange
543 circumstances, and we need to make sure that the focus indication
544 is correct.
545 */
546 setFocusedWindow(focus);
547 } else {
548 // we have no idea where focus went... so we set it to somewhere
549 setFocusedWindow(0);
550 }
551 }
552 }
553
554 break;
555 }
556
557 case ClientMessage: {
558 if (e->xclient.format == 32) {
559 if (e->xclient.message_type == xatom->getAtom(XAtom::wm_change_state)) {
560 // WM_CHANGE_STATE message
561 BlackboxWindow *win = searchWindow(e->xclient.window);
562 if (! win || ! win->validateClient()) return;
563
564 if (e->xclient.data.l[0] == IconicState)
565 win->iconify();
566 if (e->xclient.data.l[0] == NormalState)
567 win->deiconify();
568 } else if (e->xclient.message_type ==
569 xatom->getAtom(XAtom::blackbox_change_workspace) ||
570 e->xclient.message_type ==
571 xatom->getAtom(XAtom::net_current_desktop)) {
572 // NET_CURRENT_DESKTOP message
573 BScreen *screen = searchScreen(e->xclient.window);
574
575 unsigned int workspace = e->xclient.data.l[0];
576 if (screen && workspace < screen->getWorkspaceCount())
577 screen->changeWorkspaceID(workspace);
578 } else if (e->xclient.message_type ==
579 xatom->getAtom(XAtom::blackbox_change_window_focus)) {
580 // TEMP HACK TO KEEP BBKEYS WORKING
581 BlackboxWindow *win = searchWindow(e->xclient.window);
582
583 if (win && win->isVisible() && win->setInputFocus())
584 win->installColormap(True);
585 } else if (e->xclient.message_type ==
586 xatom->getAtom(XAtom::net_active_window)) {
587 // NET_ACTIVE_WINDOW
588 BlackboxWindow *win = searchWindow(e->xclient.window);
589
590 if (win) {
591 BScreen *screen = win->getScreen();
592
593 if (win->isIconic())
594 win->deiconify(False, False);
595 if (! win->isStuck() &&
596 (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
597 no_focus = True;
598 screen->changeWorkspaceID(win->getWorkspaceNumber());
599 }
600 if (win->isVisible() && win->setInputFocus()) {
601 win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
602 raiseWindow(win);
603 win->installColormap(True);
604 }
605 }
606 } else if (e->xclient.message_type ==
607 xatom->getAtom(XAtom::blackbox_cycle_window_focus)) {
608 // BLACKBOX_CYCLE_WINDOW_FOCUS
609 BScreen *screen = searchScreen(e->xclient.window);
610
611 if (screen) {
612 if (! e->xclient.data.l[0])
613 screen->prevFocus();
614 else
615 screen->nextFocus();
616 }
617 } else if (e->xclient.message_type ==
618 xatom->getAtom(XAtom::net_wm_desktop)) {
619 // NET_WM_DESKTOP
620 BlackboxWindow *win = searchWindow(e->xclient.window);
621
622 if (win) {
623 BScreen *screen = win->getScreen();
624 unsigned long wksp = (unsigned) e->xclient.data.l[0];
625 if (wksp < screen->getWorkspaceCount()) {
626 if (win->isIconic()) win->deiconify(False, True);
627 if (win->isStuck()) win->stick();
628 if (wksp != screen->getCurrentWorkspaceID())
629 win->withdraw();
630 else
631 win->show();
632 screen->reassociateWindow(win, wksp, True);
633 } else if (wksp == 0xfffffffe || // XXX: BUG, BUT DOING THIS SO KDE WORKS FOR NOW!!
634 wksp == 0xffffffff) {
635 if (win->isIconic()) win->deiconify(False, True);
636 if (! win->isStuck()) win->stick();
637 if (! win->isVisible()) win->show();
638 }
639 }
640 } else if (e->xclient.message_type ==
641 xatom->getAtom(XAtom::blackbox_change_attributes)) {
642 // BLACKBOX_CHANGE_ATTRIBUTES
643 BlackboxWindow *win = searchWindow(e->xclient.window);
644
645 if (win && win->validateClient()) {
646 BlackboxHints net;
647 net.flags = e->xclient.data.l[0];
648 net.attrib = e->xclient.data.l[1];
649 net.workspace = e->xclient.data.l[2];
650 net.stack = e->xclient.data.l[3];
651 net.decoration = e->xclient.data.l[4];
652
653 win->changeBlackboxHints(&net);
654 }
655 } else if (e->xclient.message_type ==
656 xatom->getAtom(XAtom::net_number_of_desktops)) {
657 // NET_NUMBER_OF_DESKTOPS
658 BScreen *screen = searchScreen(e->xclient.window);
659
660 if (e->xclient.data.l[0] > 0)
661 screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
662 } else if (e->xclient.message_type ==
663 xatom->getAtom(XAtom::net_close_window)) {
664 // NET_CLOSE_WINDOW
665 BlackboxWindow *win = searchWindow(e->xclient.window);
666 if (win && win->validateClient())
667 win->close(); // could this be smarter?
668 } else if (e->xclient.message_type ==
669 xatom->getAtom(XAtom::net_wm_moveresize)) {
670 // NET_WM_MOVERESIZE
671 BlackboxWindow *win = searchWindow(e->xclient.window);
672 if (win && win->validateClient()) {
673 int x_root = e->xclient.data.l[0],
674 y_root = e->xclient.data.l[1];
675 if ((Atom) e->xclient.data.l[2] ==
676 xatom->getAtom(XAtom::net_wm_moveresize_move)) {
677 win->beginMove(x_root, y_root);
678 } else {
679 if ((Atom) e->xclient.data.l[2] ==
680 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
681 win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
682 else if ((Atom) e->xclient.data.l[2] ==
683 xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
684 win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
685 else if ((Atom) e->xclient.data.l[2] ==
686 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
687 win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
688 else if ((Atom) e->xclient.data.l[2] ==
689 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
690 win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
691 }
692 }
693 } else if (e->xclient.message_type ==
694 xatom->getAtom(XAtom::net_wm_state)) {
695 // NET_WM_STATE
696 BlackboxWindow *win = searchWindow(e->xclient.window);
697 if (win && win->validateClient()) {
698 const Atom action = (Atom) e->xclient.data.l[0];
699 const Atom state[] = { (Atom) e->xclient.data.l[1],
700 (Atom) e->xclient.data.l[2] };
701
702 for (int i = 0; i < 2; ++i) {
703 if (! state[i])
704 continue;
705
706 if ((Atom) e->xclient.data.l[0] == 1) {
707 // ADD
708 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
709 win->setModal(True);
710 } else if (state[i] ==
711 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
712 if (win->isMaximizedHoriz()) {
713 win->maximize(0); // unmaximize
714 win->maximize(1); // full
715 } else if (! win->isMaximized()) {
716 win->maximize(2); // vert
717 }
718 } else if (state[i] ==
719 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
720 if (win->isMaximizedVert()) {
721 win->maximize(0); // unmaximize
722 win->maximize(1); // full
723 } else if (! win->isMaximized()) {
724 win->maximize(3); // horiz
725 }
726 } else if (state[i] ==
727 xatom->getAtom(XAtom::net_wm_state_shaded)) {
728 if (! win->isShaded())
729 win->shade();
730 } else if (state[i] ==
731 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
732 win->setSkipTaskbar(True);
733 } else if (state[i] ==
734 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
735 win->setSkipPager(True);
736 } else if (state[i] ==
737 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
738 win->setFullscreen(True);
739 }
740 } else if (action == 0) {
741 // REMOVE
742 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
743 win->setModal(False);
744 } else if (state[i] ==
745 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
746 if (win->isMaximizedFull()) {
747 win->maximize(0); // unmaximize
748 win->maximize(3); // horiz
749 } else if (win->isMaximizedVert()) {
750 win->maximize(0); // unmaximize
751 }
752 } else if (state[i] ==
753 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
754 if (win->isMaximizedFull()) {
755 win->maximize(0); // unmaximize
756 win->maximize(2); // vert
757 } else if (win->isMaximizedHoriz()) {
758 win->maximize(0); // unmaximize
759 }
760 } else if (state[i] ==
761 xatom->getAtom(XAtom::net_wm_state_shaded)) {
762 if (win->isShaded())
763 win->shade();
764 } else if (state[i] ==
765 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
766 win->setSkipTaskbar(False);
767 } else if (state[i] ==
768 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
769 win->setSkipPager(False);
770 } else if (state[i] ==
771 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
772 win->setFullscreen(False);
773 }
774 } else if (action == 2) {
775 // TOGGLE
776 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
777 win->setModal(! win->isModal());
778 } else if (state[i] ==
779 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
780 if (win->isMaximizedFull()) {
781 win->maximize(0); // unmaximize
782 win->maximize(3); // horiz
783 } else if (win->isMaximizedVert()) {
784 win->maximize(0); // unmaximize
785 } else if (win->isMaximizedHoriz()) {
786 win->maximize(0); // unmaximize
787 win->maximize(1); // full
788 } else {
789 win->maximize(2); // vert
790 }
791 } else if (state[i] ==
792 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
793 if (win->isMaximizedFull()) {
794 win->maximize(0); // unmaximize
795 win->maximize(2); // vert
796 } else if (win->isMaximizedHoriz()) {
797 win->maximize(0); // unmaximize
798 } else if (win->isMaximizedVert()) {
799 win->maximize(0); // unmaximize
800 win->maximize(1); // full
801 } else {
802 win->maximize(3); // horiz
803 }
804 } else if (state[i] ==
805 xatom->getAtom(XAtom::net_wm_state_shaded)) {
806 win->shade();
807 } else if (state[i] ==
808 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
809 win->setSkipTaskbar(! win->skipTaskbar());
810 } else if (state[i] ==
811 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
812 win->setSkipPager(! win->skipPager());
813 } else if (state[i] ==
814 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
815 win->setFullscreen(! win->isFullscreen());
816 }
817 }
818 }
819 }
820 }
821 }
822
823 break;
824 }
825
826 case NoExpose:
827 case ConfigureNotify:
828 case MapNotify:
829 break; // not handled, just ignore
830
831 default: {
832 #ifdef SHAPE
833 if (e->type == getShapeEventBase()) {
834 XShapeEvent *shape_event = (XShapeEvent *) e;
835 BlackboxWindow *win = searchWindow(e->xany.window);
836
837 if (win && shape_event->kind == ShapeBounding)
838 win->shapeEvent(shape_event);
839 }
840 #endif // SHAPE
841 }
842 } // switch
843 }
844
845
846 bool Blackbox::handleSignal(int sig) {
847 switch (sig) {
848 case SIGHUP:
849 reconfigure();
850 break;
851
852 case SIGUSR1:
853 restart();
854 break;
855
856 case SIGUSR2:
857 break;
858
859 case SIGPIPE:
860 case SIGSEGV:
861 case SIGFPE:
862 case SIGINT:
863 case SIGTERM:
864 shutdown();
865
866 default:
867 return False;
868 }
869
870 return True;
871 }
872
873
874 bool Blackbox::validateWindow(Window window) {
875 XEvent event;
876 if (XCheckTypedWindowEvent(otk::OBDisplay::display, window, DestroyNotify, &event)) {
877 XPutBackEvent(otk::OBDisplay::display, &event);
878
879 return False;
880 }
881
882 return True;
883 }
884
885
886 BScreen *Blackbox::searchScreen(Window window) {
887 ScreenList::iterator it = screenList.begin();
888
889 for (; it != screenList.end(); ++it) {
890 BScreen *s = *it;
891 if (s->getRootWindow() == window)
892 return s;
893 }
894
895 return (BScreen *) 0;
896 }
897
898
899 BScreen *Blackbox::searchSystrayWindow(Window window) {
900 WindowScreenLookup::iterator it = systraySearchList.find(window);
901 if (it != systraySearchList.end())
902 return it->second;
903
904 return (BScreen*) 0;
905 }
906
907
908 BlackboxWindow *Blackbox::searchWindow(Window window) {
909 WindowLookup::iterator it = windowSearchList.find(window);
910 if (it != windowSearchList.end())
911 return it->second;
912
913 return (BlackboxWindow*) 0;
914 }
915
916
917 BWindowGroup *Blackbox::searchGroup(Window window) {
918 GroupLookup::iterator it = groupSearchList.find(window);
919 if (it != groupSearchList.end())
920 return it->second;
921
922 return (BWindowGroup *) 0;
923 }
924
925
926 void Blackbox::saveSystrayWindowSearch(Window window, BScreen *screen) {
927 systraySearchList.insert(WindowScreenLookupPair(window, screen));
928 }
929
930
931 void Blackbox::saveWindowSearch(Window window, BlackboxWindow *data) {
932 windowSearchList.insert(WindowLookupPair(window, data));
933 }
934
935
936 void Blackbox::saveGroupSearch(Window window, BWindowGroup *data) {
937 groupSearchList.insert(GroupLookupPair(window, data));
938 }
939
940
941 void Blackbox::removeSystrayWindowSearch(Window window) {
942 systraySearchList.erase(window);
943 }
944
945
946 void Blackbox::removeWindowSearch(Window window) {
947 windowSearchList.erase(window);
948 }
949
950
951 void Blackbox::removeGroupSearch(Window window) {
952 groupSearchList.erase(window);
953 }
954
955
956 void Blackbox::restart(const char *prog) {
957 shutdown();
958
959 if (prog) {
960 putenv(const_cast<char *>(screenList.front()->displayString().c_str()));
961 execlp(prog, prog, NULL);
962 perror(prog);
963 }
964
965 // fall back in case the above execlp doesn't work
966 execvp(argv[0], argv);
967 string name = ::basename(argv[0]);
968 execvp(name.c_str(), argv);
969 }
970
971
972 void Blackbox::shutdown(void) {
973 Openbox::shutdown();
974
975 XSetInputFocus(otk::OBDisplay::display, PointerRoot, None, CurrentTime);
976
977 std::for_each(screenList.begin(), screenList.end(),
978 std::mem_fun(&BScreen::shutdown));
979
980 XSync(otk::OBDisplay::display, False);
981 }
982
983
984 #ifdef XINERAMA
985 void Blackbox::saveXineramaPlacement(bool x) {
986 resource.xinerama_placement = x;
987 config.setValue("session.xineramaSupport.windowPlacement",
988 resource.xinerama_placement);
989 reconfigure(); // make sure all screens get this
990
991 void Blackbox::saveXineramaMaximizing(bool x) {
992 resource.xinerama_maximize = x;
993 config.setValue("session.xineramaSupport.windowMaximizing",
994 resource.xinerama_maximize);
995 reconfigure(); // make sure all screens get this change
996 }
997
998
999 void Blackbox::saveXineramaSnapping(bool x) {
1000 resource.xinerama_snap = x;
1001 config.setValue("session.xineramaSupport.windowSnapping",
1002 resource.xinerama_snap);
1003 reconfigure(); // make sure all screens get this change
1004 }
1005 #endif // XINERAMA
1006
1007
1008 /*
1009 * Save all values as they are so that the defaults will be written to the rc
1010 * file
1011 */
1012 void Blackbox::save_rc(void) {
1013 config.setAutoSave(false);
1014
1015 config.setValue("session.colorsPerChannel", resource.colors_per_channel);
1016 config.setValue("session.doubleClickInterval",
1017 resource.double_click_interval);
1018 config.setValue("session.autoRaiseDelay",
1019 ((resource.auto_raise_delay.tv_sec * 1000) +
1020 (resource.auto_raise_delay.tv_usec / 1000)));
1021 config.setValue("session.cacheLife", resource.cache_life / 60000);
1022 config.setValue("session.cacheMax", resource.cache_max);
1023 config.setValue("session.styleFile", resource.style_file);
1024 config.setValue("session.titlebarLayout", resource.titlebar_layout);
1025
1026 string s;
1027 if (resource.mod_mask & Mod1Mask) s += "Mod1-";
1028 if (resource.mod_mask & Mod2Mask) s += "Mod2-";
1029 if (resource.mod_mask & Mod3Mask) s += "Mod3-";
1030 if (resource.mod_mask & Mod4Mask) s += "Mod4-";
1031 if (resource.mod_mask & Mod5Mask) s += "Mod5-";
1032 if (resource.mod_mask & ShiftMask) s += "Shift-";
1033 if (resource.mod_mask & ControlMask) s += "Control-";
1034 s.resize(s.size() - 1); // drop the last '-'
1035 config.setValue("session.modifierMask", s);
1036
1037 #ifdef XINERAMA
1038 saveXineramaPlacement(resource.xinerama_placement);
1039 saveXineramaMaximizing(resource.xinerama_maximize);
1040 saveXineramaSnapping(resource.xinerama_snap);
1041 #endif // XINERAMA
1042
1043 std::for_each(screenList.begin(), screenList.end(),
1044 std::mem_fun(&BScreen::save_rc));
1045
1046 config.setAutoSave(true);
1047 config.save();
1048 }
1049
1050
1051 void Blackbox::load_rc(void) {
1052 if (! config.load())
1053 config.create();
1054
1055 string s;
1056
1057 if (! config.getValue("session.colorsPerChannel",
1058 resource.colors_per_channel))
1059 resource.colors_per_channel = 4;
1060 if (resource.colors_per_channel < 2) resource.colors_per_channel = 2;
1061 else if (resource.colors_per_channel > 6) resource.colors_per_channel = 6;
1062
1063 if (config.getValue("session.styleFile", s))
1064 resource.style_file = expandTilde(s);
1065 else
1066 resource.style_file = DEFAULTSTYLE;
1067
1068 if (! config.getValue("session.doubleClickInterval",
1069 resource.double_click_interval));
1070 resource.double_click_interval = 250;
1071
1072 if (! config.getValue("session.autoRaiseDelay",
1073 resource.auto_raise_delay.tv_usec))
1074 resource.auto_raise_delay.tv_usec = 400;
1075 resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000;
1076 resource.auto_raise_delay.tv_usec -=
1077 (resource.auto_raise_delay.tv_sec * 1000);
1078 resource.auto_raise_delay.tv_usec *= 1000;
1079
1080 if (! config.getValue("session.cacheLife", resource.cache_life))
1081 resource.cache_life = 5;
1082 resource.cache_life *= 60000;
1083
1084 if (! config.getValue("session.cacheMax", resource.cache_max))
1085 resource.cache_max = 200;
1086
1087 if (! config.getValue("session.titlebarLayout", resource.titlebar_layout))
1088 resource.titlebar_layout = "ILMC";
1089
1090 #ifdef XINERAMA
1091 if (! config.getValue("session.xineramaSupport.windowPlacement",
1092 resource.xinerama_placement))
1093 resource.xinerama_placement = false;
1094
1095 if (! config.getValue("session.xineramaSupport.windowMaximizing",
1096 resource.xinerama_maximize))
1097 resource.xinerama_maximize = false;
1098
1099 if (! config.getValue("session.xineramaSupport.windowSnapping",
1100 resource.xinerama_snap))
1101 resource.xinerama_snap = false;
1102 #endif // XINERAMA
1103
1104 resource.mod_mask = 0;
1105 if (config.getValue("session.modifierMask", s)) {
1106 if (s.find("Mod1") != string::npos)
1107 resource.mod_mask |= Mod1Mask;
1108 if (s.find("Mod2") != string::npos)
1109 resource.mod_mask |= Mod2Mask;
1110 if (s.find("Mod3") != string::npos)
1111 resource.mod_mask |= Mod3Mask;
1112 if (s.find("Mod4") != string::npos)
1113 resource.mod_mask |= Mod4Mask;
1114 if (s.find("Mod5") != string::npos)
1115 resource.mod_mask |= Mod5Mask;
1116 if (s.find("Shift") != string::npos)
1117 resource.mod_mask |= ShiftMask;
1118 if (s.find("Control") != string::npos)
1119 resource.mod_mask |= ControlMask;
1120 }
1121 if (! resource.mod_mask)
1122 resource.mod_mask = Mod1Mask;
1123 }
1124
1125
1126 void Blackbox::reconfigure(void) {
1127 // don't reconfigure while saving the initial rc file, it's a waste and it
1128 // breaks somethings (workspace names)
1129 if (state() == Openbox::State_Starting) return;
1130
1131 reconfigure_wait = True;
1132
1133 if (! timer->isTiming()) timer->start();
1134 }
1135
1136
1137 void Blackbox::real_reconfigure(void) {
1138 load_rc();
1139
1140 otk::OBDisplay::gcCache()->purge();
1141
1142 std::for_each(screenList.begin(), screenList.end(),
1143 std::mem_fun(&BScreen::reconfigure));
1144 }
1145
1146
1147 void Blackbox::saveStyleFilename(const string& filename) {
1148 assert(! filename.empty());
1149 resource.style_file = filename;
1150 config.setValue("session.styleFile", resource.style_file);
1151 }
1152
1153
1154 void Blackbox::timeout(void) {
1155 if (reconfigure_wait)
1156 real_reconfigure();
1157
1158 reconfigure_wait = False;
1159 }
1160
1161
1162 void Blackbox::setChangingWindow(BlackboxWindow *win) {
1163 // make sure one of the two is null and the other isn't
1164 assert((! changing_window && win) || (! win && changing_window));
1165 changing_window = win;
1166 }
1167
1168
1169 void Blackbox::setFocusedWindow(BlackboxWindow *win) {
1170 if (focused_window && focused_window == win) // nothing to do
1171 return;
1172
1173 BScreen *old_screen = 0;
1174
1175 if (focused_window) {
1176 focused_window->setFocusFlag(False);
1177 old_screen = focused_window->getScreen();
1178 }
1179
1180 if (win && ! win->isIconic()) {
1181 // the active screen is the one with the last focused window...
1182 // this will keep focus on this screen no matter where the mouse goes,
1183 // so multihead keybindings will continue to work on that screen until the
1184 // user focuses a window on a different screen.
1185 active_screen = win->getScreen();
1186 focused_window = win;
1187 } else {
1188 focused_window = 0;
1189 if (! old_screen) {
1190 if (active_screen) {
1191 // set input focus to the toolbar of the screen with mouse
1192 XSetInputFocus(otk::OBDisplay::display,
1193 active_screen->getRootWindow(),
1194 RevertToPointerRoot, CurrentTime);
1195 } else {
1196 // set input focus to the toolbar of the first managed screen
1197 XSetInputFocus(otk::OBDisplay::display,
1198 screenList.front()->getRootWindow(),
1199 RevertToPointerRoot, CurrentTime);
1200 }
1201 } else {
1202 // set input focus to the toolbar of the last screen
1203 XSetInputFocus(otk::OBDisplay::display, old_screen->getRootWindow(),
1204 RevertToPointerRoot, CurrentTime);
1205 }
1206 }
1207
1208 if (active_screen && active_screen->isScreenManaged()) {
1209 active_screen->updateNetizenWindowFocus();
1210 }
1211
1212 if (old_screen && old_screen != active_screen) {
1213 old_screen->updateNetizenWindowFocus();
1214 }
1215 }
1216
1217
1218 void Blackbox::addTimer(BTimer *timer) {
1219 (void)timer;
1220 }
1221
1222
1223 void Blackbox::removeTimer(BTimer *timer) {
1224 (void)timer;
1225 }
1226
1227
1228 }
This page took 0.091805 seconds and 4 git commands to generate.