]> Dogcows Code - chaz/openbox/blob - src/screen.cc
otk::Timer-ng!! thanks ManMower for this shizznit!
[chaz/openbox] / src / screen.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 extern "C" {
8 #ifdef HAVE_STDIO_H
9 # include <stdio.h>
10 #endif // HAVE_STDIO_H
11
12 #ifdef HAVE_STRING_H
13 # include <string.h>
14 #endif // HAVE_STRING_H
15
16 #ifdef HAVE_UNISTD_H
17 # include <sys/types.h>
18 # include <unistd.h>
19 #endif // HAVE_UNISTD_H
20
21 #include "gettext.h"
22 #define _(str) gettext(str)
23 }
24
25 #include "screen.hh"
26 #include "client.hh"
27 #include "openbox.hh"
28 #include "frame.hh"
29 #include "bindings.hh"
30 #include "python.hh"
31 #include "otk/display.hh"
32
33 #include <vector>
34 #include <algorithm>
35
36 static bool running;
37 static int anotherWMRunning(Display *display, XErrorEvent *) {
38 printf(_("Another window manager already running on display %s.\n"),
39 DisplayString(display));
40 running = true;
41 return -1;
42 }
43
44
45 namespace ob {
46
47
48 Screen::Screen(int screen)
49 : WidgetBase(WidgetBase::Type_Root),
50 _number(screen)
51 {
52 assert(screen >= 0); assert(screen < ScreenCount(**otk::display));
53 _info = otk::display->screenInfo(screen);
54
55 ::running = false;
56 XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
57 XSelectInput(**otk::display, _info->rootWindow(),
58 Screen::event_mask);
59 XSync(**otk::display, false);
60 XSetErrorHandler(old);
61
62 _managed = !::running;
63 if (! _managed) return; // was unable to manage the screen
64
65 printf(_("Managing screen %d: visual 0x%lx, depth %d\n"),
66 _number, XVisualIDFromVisual(_info->visual()), _info->depth());
67
68 openbox->property()->set(_info->rootWindow(),
69 otk::Property::openbox_pid,
70 otk::Property::Atom_Cardinal,
71 (unsigned long) getpid());
72
73 // set the mouse cursor for the root window (the default cursor)
74 XDefineCursor(**otk::display, _info->rootWindow(),
75 openbox->cursors().session);
76
77 // initialize the shit that is used for all drawing on the screen
78 _image_control = new otk::ImageControl(_info, true);
79 _image_control->installRootColormap();
80 _root_cmap_installed = True;
81
82 // initialize the screen's style
83 _style.setImageControl(_image_control);
84 otk::ustring stylepath;
85 python_get_string("theme", &stylepath);
86 otk::Configuration sconfig(false);
87 sconfig.setFile(otk::expandTilde(stylepath.c_str()));
88 if (!sconfig.load()) {
89 sconfig.setFile(otk::expandTilde(DEFAULTSTYLE));
90 if (!sconfig.load()) {
91 printf(_("Unable to load default style: %s. Aborting.\n"), DEFAULTSTYLE);
92 ::exit(1);
93 }
94 }
95 _style.load(sconfig);
96
97 // set up notification of netwm support
98 changeSupportedAtoms();
99
100 // Set the netwm properties for geometry
101 unsigned long geometry[] = { _info->width(),
102 _info->height() };
103 openbox->property()->set(_info->rootWindow(),
104 otk::Property::net_desktop_geometry,
105 otk::Property::Atom_Cardinal,
106 geometry, 2);
107
108 // Set the net_desktop_names property
109 std::vector<otk::ustring> names;
110 python_get_stringlist("desktop_names", &names);
111 openbox->property()->set(_info->rootWindow(),
112 otk::Property::net_desktop_names,
113 otk::Property::utf8,
114 names);
115 // the above set() will cause the updateDesktopNames to fire right away so
116 // we have a list of desktop names
117
118 if (!python_get_long("number_of_desktops", &_num_desktops))
119 _num_desktops = 1;
120 changeNumDesktops(_num_desktops); // set the hint
121
122 _desktop = 0;
123 changeDesktop(0); // set the hint
124
125 // create the window which gets focus when no clients get it
126 XSetWindowAttributes attr;
127 attr.override_redirect = true;
128 _focuswindow = XCreateWindow(**otk::display, _info->rootWindow(),
129 -100, -100, 1, 1, 0, 0, InputOnly,
130 _info->visual(), CWOverrideRedirect, &attr);
131 XMapWindow(**otk::display, _focuswindow);
132
133 // these may be further updated if any pre-existing windows are found in
134 // the manageExising() function
135 changeClientList(); // initialize the client lists, which will be empty
136 calcArea(); // initialize the available working area
137
138 // register this class as the event handler for the root window
139 openbox->registerHandler(_info->rootWindow(), this);
140
141 // call the python Startup callbacks
142 EventData data(_number, 0, EventShutdown, 0);
143 openbox->bindings()->fireEvent(&data);
144 }
145
146
147 Screen::~Screen()
148 {
149 if (! _managed) return;
150
151 XSelectInput(**otk::display, _info->rootWindow(), NoEventMask);
152
153 // unmanage all windows
154 while (!clients.empty())
155 unmanageWindow(clients.front());
156
157 // call the python Shutdown callbacks
158 EventData data(_number, 0, EventShutdown, 0);
159 openbox->bindings()->fireEvent(&data);
160
161 XDestroyWindow(**otk::display, _focuswindow);
162 XDestroyWindow(**otk::display, _supportwindow);
163
164 delete _image_control;
165 }
166
167
168 void Screen::manageExisting()
169 {
170 unsigned int i, j, nchild;
171 Window r, p, *children;
172 XQueryTree(**otk::display, _info->rootWindow(), &r, &p,
173 &children, &nchild);
174
175 // preen the window list of all icon windows... for better dockapp support
176 for (i = 0; i < nchild; i++) {
177 if (children[i] == None) continue;
178
179 XWMHints *wmhints = XGetWMHints(**otk::display,
180 children[i]);
181
182 if (wmhints) {
183 if ((wmhints->flags & IconWindowHint) &&
184 (wmhints->icon_window != children[i])) {
185 for (j = 0; j < nchild; j++) {
186 if (children[j] == wmhints->icon_window) {
187 children[j] = None;
188 break;
189 }
190 }
191 }
192
193 XFree(wmhints);
194 }
195 }
196
197 // manage shown windows
198 for (i = 0; i < nchild; ++i) {
199 if (children[i] == None)
200 continue;
201
202 XWindowAttributes attrib;
203 if (XGetWindowAttributes(**otk::display, children[i], &attrib)) {
204 if (attrib.override_redirect) continue;
205
206 if (attrib.map_state != IsUnmapped) {
207 manageWindow(children[i]);
208 }
209 }
210 }
211
212 XFree(children);
213 }
214
215
216 void Screen::updateStrut()
217 {
218 _strut.left = _strut.right = _strut.top = _strut.bottom = 0;
219
220 Client::List::iterator it, end = clients.end();
221 for (it = clients.begin(); it != end; ++it) {
222 const otk::Strut &s = (*it)->strut();
223 _strut.left = std::max(_strut.left, s.left);
224 _strut.right = std::max(_strut.right, s.right);
225 _strut.top = std::max(_strut.top, s.top);
226 _strut.bottom = std::max(_strut.bottom, s.bottom);
227 }
228 calcArea();
229 }
230
231
232 void Screen::calcArea()
233 {
234 otk::Rect old_area = _area;
235
236 /*
237 #ifdef XINERAMA
238 // reset to the full areas
239 if (isXineramaActive())
240 xineramaUsableArea = getXineramaAreas();
241 #endif // XINERAMA
242 */
243
244 _area.setRect(_strut.left, _strut.top,
245 _info->width() - (_strut.left + _strut.right),
246 _info->height() - (_strut.top + _strut.bottom));
247
248 /*
249 #ifdef XINERAMA
250 if (isXineramaActive()) {
251 // keep each of the ximerama-defined areas inside the strut
252 RectList::iterator xit, xend = xineramaUsableArea.end();
253 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
254 if (xit->x() < usableArea.x()) {
255 xit->setX(usableArea.x());
256 xit->setWidth(xit->width() - usableArea.x());
257 }
258 if (xit->y() < usableArea.y()) {
259 xit->setY(usableArea.y());
260 xit->setHeight(xit->height() - usableArea.y());
261 }
262 if (xit->x() + xit->width() > usableArea.width())
263 xit->setWidth(usableArea.width() - xit->x());
264 if (xit->y() + xit->height() > usableArea.height())
265 xit->setHeight(usableArea.height() - xit->y());
266 }
267 }
268 #endif // XINERAMA
269 */
270
271 if (old_area != _area)
272 // XXX: re-maximize windows
273
274 changeWorkArea();
275 }
276
277
278 void Screen::changeSupportedAtoms()
279 {
280 // create the netwm support window
281 _supportwindow = XCreateSimpleWindow(**otk::display,
282 _info->rootWindow(),
283 0, 0, 1, 1, 0, 0, 0);
284
285 // set supporting window
286 openbox->property()->set(_info->rootWindow(),
287 otk::Property::net_supporting_wm_check,
288 otk::Property::Atom_Window,
289 _supportwindow);
290
291 //set properties on the supporting window
292 openbox->property()->set(_supportwindow,
293 otk::Property::net_wm_name,
294 otk::Property::utf8,
295 "Openbox");
296 openbox->property()->set(_supportwindow,
297 otk::Property::net_supporting_wm_check,
298 otk::Property::Atom_Window,
299 _supportwindow);
300
301
302 Atom supported[] = {
303 otk::Property::net_current_desktop,
304 otk::Property::net_number_of_desktops,
305 otk::Property::net_desktop_geometry,
306 otk::Property::net_desktop_viewport,
307 otk::Property::net_active_window,
308 otk::Property::net_workarea,
309 otk::Property::net_client_list,
310 otk::Property::net_client_list_stacking,
311 otk::Property::net_desktop_names,
312 otk::Property::net_close_window,
313 otk::Property::net_wm_name,
314 otk::Property::net_wm_visible_name,
315 otk::Property::net_wm_icon_name,
316 otk::Property::net_wm_visible_icon_name,
317 /*
318 otk::Property::net_wm_desktop,
319 */
320 otk::Property::net_wm_strut,
321 otk::Property::net_wm_window_type,
322 otk::Property::net_wm_window_type_desktop,
323 otk::Property::net_wm_window_type_dock,
324 otk::Property::net_wm_window_type_toolbar,
325 otk::Property::net_wm_window_type_menu,
326 otk::Property::net_wm_window_type_utility,
327 otk::Property::net_wm_window_type_splash,
328 otk::Property::net_wm_window_type_dialog,
329 otk::Property::net_wm_window_type_normal,
330 /*
331 otk::Property::net_wm_moveresize,
332 otk::Property::net_wm_moveresize_size_topleft,
333 otk::Property::net_wm_moveresize_size_topright,
334 otk::Property::net_wm_moveresize_size_bottomleft,
335 otk::Property::net_wm_moveresize_size_bottomright,
336 otk::Property::net_wm_moveresize_move,
337 */
338 /*
339 otk::Property::net_wm_allowed_actions,
340 otk::Property::net_wm_action_move,
341 otk::Property::net_wm_action_resize,
342 otk::Property::net_wm_action_shade,
343 otk::Property::net_wm_action_maximize_horz,
344 otk::Property::net_wm_action_maximize_vert,
345 otk::Property::net_wm_action_change_desktop,
346 otk::Property::net_wm_action_close,
347 */
348 otk::Property::net_wm_state,
349 otk::Property::net_wm_state_modal,
350 otk::Property::net_wm_state_maximized_vert,
351 otk::Property::net_wm_state_maximized_horz,
352 otk::Property::net_wm_state_shaded,
353 otk::Property::net_wm_state_skip_taskbar,
354 otk::Property::net_wm_state_skip_pager,
355 otk::Property::net_wm_state_hidden,
356 otk::Property::net_wm_state_fullscreen,
357 otk::Property::net_wm_state_above,
358 otk::Property::net_wm_state_below,
359 };
360 const int num_supported = sizeof(supported)/sizeof(Atom);
361
362 // convert to the atom values
363 for (int i = 0; i < num_supported; ++i)
364 supported[i] =
365 openbox->property()->atom((otk::Property::Atoms)supported[i]);
366
367 openbox->property()->set(_info->rootWindow(),
368 otk::Property::net_supported,
369 otk::Property::Atom_Atom,
370 supported, num_supported);
371 }
372
373
374 void Screen::changeClientList()
375 {
376 Window *windows;
377 unsigned int size = clients.size();
378
379 // create an array of the window ids
380 if (size > 0) {
381 Window *win_it;
382
383 windows = new Window[size];
384 win_it = windows;
385 Client::List::const_iterator it = clients.begin();
386 const Client::List::const_iterator end = clients.end();
387 for (; it != end; ++it, ++win_it)
388 *win_it = (*it)->window();
389 } else
390 windows = (Window*) 0;
391
392 openbox->property()->set(_info->rootWindow(),
393 otk::Property::net_client_list,
394 otk::Property::Atom_Window,
395 windows, size);
396
397 if (size)
398 delete [] windows;
399
400 changeStackingList();
401 }
402
403
404 void Screen::changeStackingList()
405 {
406 Window *windows;
407 unsigned int size = _stacking.size();
408
409 assert(size == clients.size()); // just making sure.. :)
410
411
412 // create an array of the window ids
413 if (size > 0) {
414 Window *win_it;
415
416 windows = new Window[size];
417 win_it = windows;
418 Client::List::const_iterator it = _stacking.begin();
419 const Client::List::const_iterator end = _stacking.end();
420 for (; it != end; ++it, ++win_it)
421 *win_it = (*it)->window();
422 } else
423 windows = (Window*) 0;
424
425 openbox->property()->set(_info->rootWindow(),
426 otk::Property::net_client_list_stacking,
427 otk::Property::Atom_Window,
428 windows, size);
429
430 if (size)
431 delete [] windows;
432 }
433
434
435 void Screen::changeWorkArea() {
436 unsigned long *dims = new unsigned long[4 * _num_desktops];
437 for (long i = 0; i < _num_desktops; ++i) {
438 // XXX: this could be different for each workspace
439 dims[(i * 4) + 0] = _area.x();
440 dims[(i * 4) + 1] = _area.y();
441 dims[(i * 4) + 2] = _area.width();
442 dims[(i * 4) + 3] = _area.height();
443 }
444 openbox->property()->set(_info->rootWindow(),
445 otk::Property::net_workarea,
446 otk::Property::Atom_Cardinal,
447 dims, 4 * _num_desktops);
448 delete [] dims;
449 }
450
451
452 void Screen::manageWindow(Window window)
453 {
454 Client *client = 0;
455 XWMHints *wmhint;
456 XSetWindowAttributes attrib_set;
457
458 otk::display->grab();
459
460 // is the window a docking app
461 if ((wmhint = XGetWMHints(**otk::display, window))) {
462 if ((wmhint->flags & StateHint) &&
463 wmhint->initial_state == WithdrawnState) {
464 //slit->addClient(w); // XXX: make dock apps work!
465 otk::display->ungrab();
466
467 XFree(wmhint);
468 return;
469 }
470 XFree(wmhint);
471 }
472
473 // choose the events we want to receive on the CLIENT window
474 attrib_set.event_mask = Client::event_mask;
475 attrib_set.do_not_propagate_mask = Client::no_propagate_mask;
476 XChangeWindowAttributes(**otk::display, window,
477 CWEventMask|CWDontPropagate, &attrib_set);
478
479 // create the Client class, which gets all of the hints on the window
480 client = new Client(_number, window);
481 // register for events
482 openbox->registerHandler(window, client);
483 // add to the wm's map
484 openbox->addClient(window, client);
485
486 // we dont want a border on the client
487 client->toggleClientBorder(false);
488
489 // specify that if we exit, the window should not be destroyed and should be
490 // reparented back to root automatically
491 XChangeSaveSet(**otk::display, window, SetModeInsert);
492
493 if (!(openbox->state() == Openbox::State_Starting ||
494 client->positionRequested())) {
495 // position the window intelligenty .. hopefully :)
496 // call the python PLACEWINDOW binding
497 EventData data(_number, client, EventPlaceWindow, 0);
498 openbox->bindings()->fireEvent(&data);
499 }
500
501 // create the decoration frame for the client window
502 client->frame = new Frame(client, &_style);
503
504 // add to the wm's map
505 openbox->addClient(client->frame->window(), client);
506 openbox->addClient(client->frame->plate(), client);
507 openbox->addClient(client->frame->titlebar(), client);
508 openbox->addClient(client->frame->label(), client);
509 openbox->addClient(client->frame->button_max(), client);
510 openbox->addClient(client->frame->button_iconify(), client);
511 openbox->addClient(client->frame->button_stick(), client);
512 openbox->addClient(client->frame->button_close(), client);
513 openbox->addClient(client->frame->handle(), client);
514 openbox->addClient(client->frame->grip_left(), client);
515 openbox->addClient(client->frame->grip_right(), client);
516
517 // reparent the client to the frame
518 client->frame->grabClient();
519
520 // if on the current desktop.. (or all desktops)
521 if (client->desktop() == _desktop ||
522 client->desktop() == (signed)0xffffffff) {
523 client->frame->show();
524 }
525
526 // XXX: handle any requested states such as maximized
527
528 otk::display->ungrab();
529
530 // add to the screen's list
531 clients.push_back(client);
532 // this puts into the stacking order, then raises it
533 _stacking.push_back(client);
534 restack(true, client);
535 // update the root properties
536 changeClientList();
537
538 openbox->bindings()->grabButtons(true, client);
539
540 // call the python NEWWINDOW binding
541 EventData data(_number, client, EventNewWindow, 0);
542 openbox->bindings()->fireEvent(&data);
543
544 #ifdef DEBUG
545 printf("Managed window 0x%lx\n", window);
546 #endif
547 }
548
549
550 void Screen::unmanageWindow(Client *client)
551 {
552 Frame *frame = client->frame;
553
554 // call the python CLOSEWINDOW binding
555 EventData data(_number, client, EventCloseWindow, 0);
556 openbox->bindings()->fireEvent(&data);
557
558 openbox->bindings()->grabButtons(false, client);
559
560 // remove from the wm's map
561 openbox->removeClient(client->window());
562 openbox->removeClient(frame->window());
563 openbox->removeClient(frame->plate());
564 openbox->removeClient(frame->titlebar());
565 openbox->removeClient(frame->label());
566 openbox->removeClient(frame->button_max());
567 openbox->removeClient(frame->button_iconify());
568 openbox->removeClient(frame->button_stick());
569 openbox->removeClient(frame->button_close());
570 openbox->removeClient(frame->handle());
571 openbox->removeClient(frame->grip_left());
572 openbox->removeClient(frame->grip_right());
573 // unregister for handling events
574 openbox->clearHandler(client->window());
575
576 // remove the window from our save set
577 XChangeSaveSet(**otk::display, client->window(), SetModeDelete);
578
579 // we dont want events no more
580 XSelectInput(**otk::display, client->window(), NoEventMask);
581
582 frame->hide();
583
584 // give the client its border back
585 client->toggleClientBorder(true);
586
587 // reparent the window out of the frame
588 frame->releaseClient();
589
590 delete client->frame;
591 client->frame = 0;
592
593 // remove from the stacking order
594 _stacking.remove(client);
595
596 // remove from the screen's list
597 clients.remove(client);
598
599 // unfocus the client (calls the focus callbacks)
600 client->unfocus();
601
602 #ifdef DEBUG
603 printf("Unmanaged window 0x%lx\n", client->window());
604 #endif
605
606 delete client;
607
608 // update the root properties
609 changeClientList();
610 }
611
612 void Screen::restack(bool raise, Client *client)
613 {
614 const int layer = client->layer();
615 std::vector<Window> wins;
616
617 _stacking.remove(client);
618
619 // the stacking list is from highest to lowest
620
621 Client::List::iterator it = _stacking.begin(), end = _stacking.end();
622 // insert the windows above this window
623 for (; it != end; ++it) {
624 if ((*it)->layer() < layer || (raise && (*it)->layer() == layer))
625 break;
626 wins.push_back((*it)->frame->window());
627 }
628 // insert our client
629 wins.push_back(client->frame->window());
630 _stacking.insert(it, client);
631 // insert the remaining below this window
632 for (; it != end; ++it)
633 wins.push_back((*it)->frame->window());
634
635 XRestackWindows(**otk::display, &wins[0], wins.size());
636 changeStackingList();
637 }
638
639 void Screen::changeDesktop(long desktop)
640 {
641 if (!(desktop >= 0 && desktop < _num_desktops)) return;
642
643 printf("Moving to desktop %ld\n", desktop);
644
645 long old = _desktop;
646
647 _desktop = desktop;
648 openbox->property()->set(_info->rootWindow(),
649 otk::Property::net_current_desktop,
650 otk::Property::Atom_Cardinal,
651 _desktop);
652
653 if (old == _desktop) return;
654
655 Client::List::iterator it, end = clients.end();
656 for (it = clients.begin(); it != end; ++it) {
657 if ((*it)->desktop() == old) {
658 (*it)->frame->hide();
659 } else if ((*it)->desktop() == _desktop) {
660 (*it)->frame->show();
661 }
662 }
663
664 // force the callbacks to fire
665 if (!openbox->focusedClient())
666 openbox->setFocusedClient(0);
667 }
668
669 void Screen::changeNumDesktops(long num)
670 {
671 assert(num > 0);
672
673 if (!(num > 0)) return;
674
675 // XXX: move windows on desktops that will no longer exist!
676
677 _num_desktops = num;
678 openbox->property()->set(_info->rootWindow(),
679 otk::Property::net_number_of_desktops,
680 otk::Property::Atom_Cardinal,
681 _num_desktops);
682
683 // set the viewport hint
684 unsigned long *viewport = new unsigned long[_num_desktops * 2];
685 memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
686 openbox->property()->set(_info->rootWindow(),
687 otk::Property::net_desktop_viewport,
688 otk::Property::Atom_Cardinal,
689 viewport, _num_desktops * 2);
690 delete [] viewport;
691
692 // update the work area hint
693 changeWorkArea();
694 }
695
696
697 void Screen::updateDesktopNames()
698 {
699 const otk::Property *property = openbox->property();
700
701 unsigned long num = (unsigned) -1;
702
703 if (!property->get(_info->rootWindow(),
704 otk::Property::net_desktop_names,
705 otk::Property::utf8, &num, &_desktop_names))
706 _desktop_names.clear();
707 while ((long)_desktop_names.size() < _num_desktops)
708 _desktop_names.push_back("Unnamed");
709 }
710
711
712 void Screen::setDesktopName(long i, const otk::ustring &name)
713 {
714 assert(i >= 0);
715
716 if (i >= _num_desktops) return;
717
718 const otk::Property *property = openbox->property();
719
720 otk::Property::StringVect newnames = _desktop_names;
721 newnames[i] = name;
722 property->set(_info->rootWindow(), otk::Property::net_desktop_names,
723 otk::Property::utf8, newnames);
724 }
725
726
727 void Screen::propertyHandler(const XPropertyEvent &e)
728 {
729 otk::EventHandler::propertyHandler(e);
730
731 const otk::Property *property = openbox->property();
732
733 // compress changes to a single property into a single change
734 XEvent ce;
735 while (XCheckTypedEvent(**otk::display, e.type, &ce)) {
736 // XXX: it would be nice to compress ALL changes to a property, not just
737 // changes in a row without other props between.
738 if (ce.xproperty.atom != e.atom) {
739 XPutBackEvent(**otk::display, &ce);
740 break;
741 }
742 }
743
744 if (e.atom == property->atom(otk::Property::net_desktop_names))
745 updateDesktopNames();
746 }
747
748
749 void Screen::clientMessageHandler(const XClientMessageEvent &e)
750 {
751 otk::EventHandler::clientMessageHandler(e);
752
753 if (e.format != 32) return;
754
755 const otk::Property *property = openbox->property();
756
757 if (e.message_type == property->atom(otk::Property::net_current_desktop)) {
758 changeDesktop(e.data.l[0]);
759 } else if (e.message_type ==
760 property->atom(otk::Property::net_number_of_desktops)) {
761 changeNumDesktops(e.data.l[0]);
762 }
763 // XXX: so many client messages to handle here! ..or not.. they go to clients
764 }
765
766
767 void Screen::mapRequestHandler(const XMapRequestEvent &e)
768 {
769 otk::EventHandler::mapRequestHandler(e);
770
771 #ifdef DEBUG
772 printf("MapRequest for 0x%lx\n", e.window);
773 #endif // DEBUG
774
775 /*
776 MapRequest events come here even after the window exists instead of going
777 right to the client window, because of how they are sent and their struct
778 layout.
779 */
780 Client *c = openbox->findClient(e.window);
781
782 if (c) {
783 // send a net_active_window message
784 XEvent ce;
785 ce.xclient.type = ClientMessage;
786 ce.xclient.message_type =
787 openbox->property()->atom(otk::Property::net_active_window);
788 ce.xclient.display = **otk::display;
789 ce.xclient.window = c->window();
790 ce.xclient.format = 32;
791 ce.xclient.data.l[0] = 0l;
792 ce.xclient.data.l[1] = 0l;
793 ce.xclient.data.l[2] = 0l;
794 ce.xclient.data.l[3] = 0l;
795 ce.xclient.data.l[4] = 0l;
796 XSendEvent(**otk::display, _info->rootWindow(), false,
797 SubstructureRedirectMask | SubstructureNotifyMask,
798 &ce);
799 } else
800 manageWindow(e.window);
801 }
802 }
This page took 0.076782 seconds and 5 git commands to generate.