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