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