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