]> Dogcows Code - chaz/openbox/blob - src/screen.cc
keep track of desktops...
[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 OBScreen::OBScreen(int screen)
49 : OBWidget(OBWidget::Type_Root),
50 _number(screen)
51 {
52 assert(screen >= 0); assert(screen < ScreenCount(otk::OBDisplay::display));
53 _info = otk::OBDisplay::screenInfo(screen);
54
55 ::running = false;
56 XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
57 XSelectInput(otk::OBDisplay::display, _info->rootWindow(),
58 OBScreen::event_mask);
59 XSync(otk::OBDisplay::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::OBProperty::openbox_pid,
70 otk::OBProperty::Atom_Cardinal,
71 (unsigned long) getpid());
72
73 // set the mouse cursor for the root window (the default cursor)
74 XDefineCursor(otk::OBDisplay::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::BImageControl(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 std::string stylepath;
86 python_get_string("theme", &stylepath);
87 otk::Configuration sconfig(false);
88 sconfig.setFile(otk::expandTilde(stylepath));
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::OBProperty::net_desktop_geometry,
106 otk::OBProperty::Atom_Cardinal,
107 geometry, 2);
108
109 // Set the net_desktop_names property
110 std::vector<std::string> names;
111 python_get_stringlist("desktop_names", &names);
112 Openbox::instance->property()->set(_info->rootWindow(),
113 otk::OBProperty::net_desktop_names,
114 otk::OBProperty::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 = 4;
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::OBDisplay::display, _info->rootWindow(),
130 -100, -100, 1, 1, 0, 0, InputOnly,
131 _info->visual(), CWOverrideRedirect, &attr);
132 XMapWindow(otk::OBDisplay::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
143
144 OBScreen::~OBScreen()
145 {
146 if (! _managed) return;
147
148 XSelectInput(otk::OBDisplay::display, _info->rootWindow(), NoEventMask);
149
150 // unmanage all windows
151 while (!clients.empty())
152 unmanageWindow(clients.front());
153
154 XDestroyWindow(otk::OBDisplay::display, _focuswindow);
155 XDestroyWindow(otk::OBDisplay::display, _supportwindow);
156
157 delete _image_control;
158 }
159
160
161 void OBScreen::manageExisting()
162 {
163 unsigned int i, j, nchild;
164 Window r, p, *children;
165 XQueryTree(otk::OBDisplay::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::OBDisplay::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::OBDisplay::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 OBScreen::updateStrut()
210 {
211 _strut.left = _strut.right = _strut.top = _strut.bottom = 0;
212
213 OBClient::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 OBScreen::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 OBScreen::changeSupportedAtoms()
272 {
273 // create the netwm support window
274 _supportwindow = XCreateSimpleWindow(otk::OBDisplay::display,
275 _info->rootWindow(),
276 0, 0, 1, 1, 0, 0, 0);
277 assert(_supportwindow != None);
278
279 // set supporting window
280 Openbox::instance->property()->set(_info->rootWindow(),
281 otk::OBProperty::net_supporting_wm_check,
282 otk::OBProperty::Atom_Window,
283 _supportwindow);
284
285 //set properties on the supporting window
286 Openbox::instance->property()->set(_supportwindow,
287 otk::OBProperty::net_wm_name,
288 otk::OBProperty::utf8,
289 "Openbox");
290 Openbox::instance->property()->set(_supportwindow,
291 otk::OBProperty::net_supporting_wm_check,
292 otk::OBProperty::Atom_Window,
293 _supportwindow);
294
295
296 Atom supported[] = {
297 otk::OBProperty::net_current_desktop,
298 otk::OBProperty::net_number_of_desktops,
299 otk::OBProperty::net_desktop_geometry,
300 otk::OBProperty::net_desktop_viewport,
301 otk::OBProperty::net_active_window,
302 otk::OBProperty::net_workarea,
303 otk::OBProperty::net_client_list,
304 otk::OBProperty::net_client_list_stacking,
305 otk::OBProperty::net_desktop_names,
306 otk::OBProperty::net_close_window,
307 otk::OBProperty::net_wm_name,
308 otk::OBProperty::net_wm_visible_name,
309 otk::OBProperty::net_wm_icon_name,
310 otk::OBProperty::net_wm_visible_icon_name,
311 /*
312 otk::OBProperty::net_wm_desktop,
313 */
314 otk::OBProperty::net_wm_strut,
315 otk::OBProperty::net_wm_window_type,
316 otk::OBProperty::net_wm_window_type_desktop,
317 otk::OBProperty::net_wm_window_type_dock,
318 otk::OBProperty::net_wm_window_type_toolbar,
319 otk::OBProperty::net_wm_window_type_menu,
320 otk::OBProperty::net_wm_window_type_utility,
321 otk::OBProperty::net_wm_window_type_splash,
322 otk::OBProperty::net_wm_window_type_dialog,
323 otk::OBProperty::net_wm_window_type_normal,
324 /*
325 otk::OBProperty::net_wm_moveresize,
326 otk::OBProperty::net_wm_moveresize_size_topleft,
327 otk::OBProperty::net_wm_moveresize_size_topright,
328 otk::OBProperty::net_wm_moveresize_size_bottomleft,
329 otk::OBProperty::net_wm_moveresize_size_bottomright,
330 otk::OBProperty::net_wm_moveresize_move,
331 */
332 /*
333 otk::OBProperty::net_wm_allowed_actions,
334 otk::OBProperty::net_wm_action_move,
335 otk::OBProperty::net_wm_action_resize,
336 otk::OBProperty::net_wm_action_shade,
337 otk::OBProperty::net_wm_action_maximize_horz,
338 otk::OBProperty::net_wm_action_maximize_vert,
339 otk::OBProperty::net_wm_action_change_desktop,
340 otk::OBProperty::net_wm_action_close,
341 */
342 otk::OBProperty::net_wm_state,
343 otk::OBProperty::net_wm_state_modal,
344 otk::OBProperty::net_wm_state_maximized_vert,
345 otk::OBProperty::net_wm_state_maximized_horz,
346 otk::OBProperty::net_wm_state_shaded,
347 otk::OBProperty::net_wm_state_skip_taskbar,
348 otk::OBProperty::net_wm_state_skip_pager,
349 otk::OBProperty::net_wm_state_hidden,
350 otk::OBProperty::net_wm_state_fullscreen,
351 otk::OBProperty::net_wm_state_above,
352 otk::OBProperty::net_wm_state_below,
353 };
354 const int num_supported = sizeof(supported)/sizeof(Atom);
355
356 // convert to the atom values
357 for (int i = 0; i < num_supported; ++i)
358 supported[i] =
359 Openbox::instance->property()->atom((otk::OBProperty::Atoms)supported[i]);
360
361 Openbox::instance->property()->set(_info->rootWindow(),
362 otk::OBProperty::net_supported,
363 otk::OBProperty::Atom_Atom,
364 supported, num_supported);
365 }
366
367
368 void OBScreen::changeClientList()
369 {
370 Window *windows;
371 unsigned int size = clients.size();
372
373 // create an array of the window ids
374 if (size > 0) {
375 Window *win_it;
376
377 windows = new Window[size];
378 win_it = windows;
379 OBClient::List::const_iterator it = clients.begin();
380 const OBClient::List::const_iterator end = clients.end();
381 for (; it != end; ++it, ++win_it)
382 *win_it = (*it)->window();
383 } else
384 windows = (Window*) 0;
385
386 Openbox::instance->property()->set(_info->rootWindow(),
387 otk::OBProperty::net_client_list,
388 otk::OBProperty::Atom_Window,
389 windows, size);
390
391 if (size)
392 delete [] windows;
393
394 changeStackingList();
395 }
396
397
398 void OBScreen::changeStackingList()
399 {
400 Window *windows;
401 unsigned int size = _stacking.size();
402
403 assert(size == clients.size()); // just making sure.. :)
404
405
406 // create an array of the window ids
407 if (size > 0) {
408 Window *win_it;
409
410 windows = new Window[size];
411 win_it = windows;
412 OBClient::List::const_iterator it = _stacking.begin();
413 const OBClient::List::const_iterator end = _stacking.end();
414 for (; it != end; ++it, ++win_it)
415 *win_it = (*it)->window();
416 } else
417 windows = (Window*) 0;
418
419 Openbox::instance->property()->set(_info->rootWindow(),
420 otk::OBProperty::net_client_list_stacking,
421 otk::OBProperty::Atom_Window,
422 windows, size);
423
424 if (size)
425 delete [] windows;
426 }
427
428
429 void OBScreen::changeWorkArea() {
430 unsigned long *dims = new unsigned long[4 * _num_desktops];
431 for (long i = 0; i < _num_desktops; ++i) {
432 // XXX: this could be different for each workspace
433 dims[(i * 4) + 0] = _area.x();
434 dims[(i * 4) + 1] = _area.y();
435 dims[(i * 4) + 2] = _area.width();
436 dims[(i * 4) + 3] = _area.height();
437 }
438 Openbox::instance->property()->set(_info->rootWindow(),
439 otk::OBProperty::net_workarea,
440 otk::OBProperty::Atom_Cardinal,
441 dims, 4 * _num_desktops);
442 delete [] dims;
443 }
444
445
446 void OBScreen::manageWindow(Window window)
447 {
448 OBClient *client = 0;
449 XWMHints *wmhint;
450 XSetWindowAttributes attrib_set;
451
452 // is the window a docking app
453 if ((wmhint = XGetWMHints(otk::OBDisplay::display, window))) {
454 if ((wmhint->flags & StateHint) &&
455 wmhint->initial_state == WithdrawnState) {
456 //slit->addClient(w); // XXX: make dock apps work!
457 XFree(wmhint);
458 return;
459 }
460 XFree(wmhint);
461 }
462
463 otk::OBDisplay::grab();
464
465 // choose the events we want to receive on the CLIENT window
466 attrib_set.event_mask = OBClient::event_mask;
467 attrib_set.do_not_propagate_mask = OBClient::no_propagate_mask;
468 XChangeWindowAttributes(otk::OBDisplay::display, window,
469 CWEventMask|CWDontPropagate, &attrib_set);
470
471 // create the OBClient class, which gets all of the hints on the window
472 client = new OBClient(_number, window);
473 // register for events
474 Openbox::instance->registerHandler(window, client);
475 // add to the wm's map
476 Openbox::instance->addClient(window, client);
477
478 // we dont want a border on the client
479 client->toggleClientBorder(false);
480
481 // specify that if we exit, the window should not be destroyed and should be
482 // reparented back to root automatically
483 XChangeSaveSet(otk::OBDisplay::display, window, SetModeInsert);
484
485 if (!client->positionRequested()) {
486 // XXX: position the window intelligenty
487 }
488
489 // create the decoration frame for the client window
490 client->frame = new OBFrame(client, &_style);
491
492 // add to the wm's map
493 Openbox::instance->addClient(client->frame->window(), client);
494 Openbox::instance->addClient(client->frame->plate(), client);
495 Openbox::instance->addClient(client->frame->titlebar(), client);
496 Openbox::instance->addClient(client->frame->label(), client);
497 Openbox::instance->addClient(client->frame->button_max(), client);
498 Openbox::instance->addClient(client->frame->button_iconify(), client);
499 Openbox::instance->addClient(client->frame->button_stick(), client);
500 Openbox::instance->addClient(client->frame->button_close(), client);
501 Openbox::instance->addClient(client->frame->handle(), client);
502 Openbox::instance->addClient(client->frame->grip_left(), client);
503 Openbox::instance->addClient(client->frame->grip_right(), client);
504
505 // XXX: if on the current desktop..
506 client->frame->show();
507
508 // XXX: handle any requested states such as maximized
509
510 otk::OBDisplay::ungrab();
511
512 // add to the screen's list
513 clients.push_back(client);
514 // this puts into the stacking order, then raises it
515 _stacking.push_back(client);
516 restack(true, client);
517 // update the root properties
518 changeClientList();
519
520 Openbox::instance->bindings()->grabButtons(true, client);
521
522 // XXX: make this optional or more intelligent
523 if (client->normal())
524 client->focus();
525
526 // call the python NEWWINDOW binding
527 EventData *data = new_event_data(window, EventNewWindow, 0);
528 Openbox::instance->bindings()->fireEvent(data);
529 Py_DECREF((PyObject*)data);
530
531 printf("Managed window 0x%lx\n", window);
532 }
533
534
535 void OBScreen::unmanageWindow(OBClient *client)
536 {
537 OBFrame *frame = client->frame;
538
539 // call the python CLOSEWINDOW binding
540 EventData *data = new_event_data(client->window(), EventCloseWindow, 0);
541 Openbox::instance->bindings()->fireEvent(data);
542 Py_DECREF((PyObject*)data);
543
544 Openbox::instance->bindings()->grabButtons(false, client);
545
546 // remove from the stacking order
547 _stacking.remove(client);
548
549 // pass around focus if this window was focused XXX do this better!
550 if (Openbox::instance->focusedClient() == client) {
551 OBClient *newfocus = 0;
552 OBClient::List::iterator it, end = _stacking.end();
553 for (it = _stacking.begin(); it != end; ++it)
554 if ((*it)->normal() && (*it)->focus()) {
555 newfocus = *it;
556 break;
557 }
558 if (!newfocus)
559 client->unfocus();
560 }
561
562 // remove from the wm's map
563 Openbox::instance->removeClient(client->window());
564 Openbox::instance->removeClient(frame->window());
565 Openbox::instance->removeClient(frame->plate());
566 Openbox::instance->removeClient(frame->titlebar());
567 Openbox::instance->removeClient(frame->label());
568 Openbox::instance->removeClient(frame->button_max());
569 Openbox::instance->removeClient(frame->button_iconify());
570 Openbox::instance->removeClient(frame->button_stick());
571 Openbox::instance->removeClient(frame->button_close());
572 Openbox::instance->removeClient(frame->handle());
573 Openbox::instance->removeClient(frame->grip_left());
574 Openbox::instance->removeClient(frame->grip_right());
575 // unregister for handling events
576 Openbox::instance->clearHandler(client->window());
577
578 // remove the window from our save set
579 XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
580
581 // we dont want events no more
582 XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
583
584 frame->hide();
585
586 // give the client its border back
587 client->toggleClientBorder(true);
588
589 delete client->frame;
590 client->frame = 0;
591
592 // remove from the screen's list
593 clients.remove(client);
594 delete client;
595
596 // update the root properties
597 changeClientList();
598 }
599
600 void OBScreen::restack(bool raise, OBClient *client)
601 {
602 const int layer = client->layer();
603 std::vector<Window> wins;
604
605 _stacking.remove(client);
606
607 // the stacking list is from highest to lowest
608
609 OBClient::List::iterator it = _stacking.begin(), end = _stacking.end();
610 // insert the windows above this window
611 for (; it != end; ++it) {
612 if ((*it)->layer() < layer || (raise && (*it)->layer() == layer))
613 break;
614 wins.push_back((*it)->frame->window());
615 }
616 // insert our client
617 wins.push_back(client->frame->window());
618 _stacking.insert(it, client);
619 // insert the remaining below this window
620 for (; it != end; ++it)
621 wins.push_back((*it)->frame->window());
622
623 XRestackWindows(otk::OBDisplay::display, &wins[0], wins.size());
624 changeStackingList();
625 }
626
627 void OBScreen::changeDesktop(long desktop)
628 {
629 assert(desktop >= 0 && desktop < _num_desktops);
630
631 if (!(desktop >= 0 && desktop < _num_desktops)) return;
632
633 long old = _desktop;
634
635 _desktop = desktop;
636 Openbox::instance->property()->set(_info->rootWindow(),
637 otk::OBProperty::net_current_desktop,
638 otk::OBProperty::Atom_Cardinal,
639 _desktop);
640
641 OBClient::List::iterator it, end = clients.end();
642 for (it = clients.begin(); it != end; ++it) {
643 if ((*it)->desktop() == old) {
644 // XXX hide
645 } else if ((*it)->desktop() == _desktop) {
646 // XXX show
647 }
648 }
649 }
650
651 void OBScreen::changeNumDesktops(long num)
652 {
653 assert(num > 0);
654
655 if (!(num > 0)) return;
656
657 _num_desktops = num;
658 Openbox::instance->property()->set(_info->rootWindow(),
659 otk::OBProperty::net_number_of_desktops,
660 otk::OBProperty::Atom_Cardinal,
661 _num_desktops);
662
663 // set the viewport hint
664 unsigned long *viewport = new unsigned long[_num_desktops * 2];
665 memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
666 Openbox::instance->property()->set(_info->rootWindow(),
667 otk::OBProperty::net_desktop_viewport,
668 otk::OBProperty::Atom_Cardinal,
669 viewport, _num_desktops * 2);
670 delete [] viewport;
671
672 // update the work area hint
673 changeWorkArea();
674 }
675
676
677 void OBScreen::updateDesktopNames()
678 {
679 const otk::OBProperty *property = Openbox::instance->property();
680
681 unsigned long num = (unsigned) -1;
682
683 if (!property->get(_info->rootWindow(),
684 otk::OBProperty::net_desktop_names,
685 otk::OBProperty::utf8, &num, &_desktop_names))
686 _desktop_names.clear();
687 while ((long)_desktop_names.size() < _num_desktops)
688 _desktop_names.push_back("Unnamed");
689 }
690
691
692 void OBScreen::setDesktopName(long i, const std::string &name)
693 {
694 assert(i >= 0);
695
696 if (i >= _num_desktops) return;
697
698 const otk::OBProperty *property = Openbox::instance->property();
699
700 otk::OBProperty::StringVect newnames = _desktop_names;
701 newnames[i] = name;
702 property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names,
703 otk::OBProperty::utf8, newnames);
704 }
705
706
707 void OBScreen::propertyHandler(const XPropertyEvent &e)
708 {
709 otk::OtkEventHandler::propertyHandler(e);
710
711 const otk::OBProperty *property = Openbox::instance->property();
712
713 // compress changes to a single property into a single change
714 XEvent ce;
715 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
716 // XXX: it would be nice to compress ALL changes to a property, not just
717 // changes in a row without other props between.
718 if (ce.xproperty.atom != e.atom) {
719 XPutBackEvent(otk::OBDisplay::display, &ce);
720 break;
721 }
722 }
723
724 if (e.atom == property->atom(otk::OBProperty::net_desktop_names))
725 updateDesktopNames();
726 }
727
728
729 void OBScreen::clientMessageHandler(const XClientMessageEvent &e)
730 {
731 otk::OtkEventHandler::clientMessageHandler(e);
732
733 if (e.format != 32) return;
734
735 const otk::OBProperty *property = Openbox::instance->property();
736
737 if (e.message_type == property->atom(otk::OBProperty::net_current_desktop)) {
738 changeDesktop(e.data.l[0]);
739 } else if (e.message_type ==
740 property->atom(otk::OBProperty::net_number_of_desktops)) {
741 changeNumDesktops(e.data.l[0]);
742 }
743 // XXX: so many client messages to handle here! ..or not.. they go to clients
744 }
745
746
747 void OBScreen::mapRequestHandler(const XMapRequestEvent &e)
748 {
749 otk::OtkEventHandler::mapRequestHandler(e);
750
751 #ifdef DEBUG
752 printf("MapRequest for 0x%lx\n", e.window);
753 #endif // DEBUG
754
755 /*
756 MapRequest events come here even after the window exists instead of going
757 right to the client window, because of how they are sent and their struct
758 layout.
759 */
760 OBClient *c = Openbox::instance->findClient(e.window);
761
762 if (c) {
763 if (c->shaded())
764 c->shade(false);
765 // XXX: uniconify the window
766 c->focus();
767 } else
768 manageWindow(e.window);
769 }
770 }
This page took 0.071523 seconds and 5 git commands to generate.