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