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