]> Dogcows Code - chaz/openbox/blob - src/screen.cc
windows stay on their 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 bool shown = false;
506
507 // if on the current desktop.. (or all desktops)
508 if (client->desktop() == _desktop ||
509 client->desktop() == (signed)0xffffffff) {
510 shown = true;
511 client->frame->show();
512 }
513
514 // XXX: handle any requested states such as maximized
515
516 otk::OBDisplay::ungrab();
517
518 // add to the screen's list
519 clients.push_back(client);
520 // this puts into the stacking order, then raises it
521 _stacking.push_back(client);
522 restack(true, client);
523 // update the root properties
524 changeClientList();
525
526 Openbox::instance->bindings()->grabButtons(true, client);
527
528 if (shown) {
529 // XXX: make this optional or more intelligent
530 if (client->normal())
531 client->focus();
532 }
533
534 // call the python NEWWINDOW binding
535 EventData *data = new_event_data(window, EventNewWindow, 0);
536 Openbox::instance->bindings()->fireEvent(data);
537 Py_DECREF((PyObject*)data);
538
539 printf("Managed window 0x%lx\n", window);
540 }
541
542
543 void OBScreen::unmanageWindow(OBClient *client)
544 {
545 OBFrame *frame = client->frame;
546
547 // call the python CLOSEWINDOW binding
548 EventData *data = new_event_data(client->window(), EventCloseWindow, 0);
549 Openbox::instance->bindings()->fireEvent(data);
550 Py_DECREF((PyObject*)data);
551
552 Openbox::instance->bindings()->grabButtons(false, client);
553
554 // remove from the stacking order
555 _stacking.remove(client);
556
557 // pass around focus if this window was focused XXX do this better!
558 if (Openbox::instance->focusedClient() == client) {
559 OBClient *newfocus = 0;
560 OBClient::List::iterator it, end = _stacking.end();
561 for (it = _stacking.begin(); it != end; ++it)
562 if ((*it)->desktop() == _desktop && (*it)->normal() && (*it)->focus()) {
563 newfocus = *it;
564 break;
565 }
566 if (!newfocus)
567 client->unfocus();
568 }
569
570 // remove from the wm's map
571 Openbox::instance->removeClient(client->window());
572 Openbox::instance->removeClient(frame->window());
573 Openbox::instance->removeClient(frame->plate());
574 Openbox::instance->removeClient(frame->titlebar());
575 Openbox::instance->removeClient(frame->label());
576 Openbox::instance->removeClient(frame->button_max());
577 Openbox::instance->removeClient(frame->button_iconify());
578 Openbox::instance->removeClient(frame->button_stick());
579 Openbox::instance->removeClient(frame->button_close());
580 Openbox::instance->removeClient(frame->handle());
581 Openbox::instance->removeClient(frame->grip_left());
582 Openbox::instance->removeClient(frame->grip_right());
583 // unregister for handling events
584 Openbox::instance->clearHandler(client->window());
585
586 // remove the window from our save set
587 XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
588
589 // we dont want events no more
590 XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
591
592 frame->hide();
593
594 // give the client its border back
595 client->toggleClientBorder(true);
596
597 delete client->frame;
598 client->frame = 0;
599
600 // remove from the screen's list
601 clients.remove(client);
602 delete client;
603
604 // update the root properties
605 changeClientList();
606 }
607
608 void OBScreen::restack(bool raise, OBClient *client)
609 {
610 const int layer = client->layer();
611 std::vector<Window> wins;
612
613 _stacking.remove(client);
614
615 // the stacking list is from highest to lowest
616
617 OBClient::List::iterator it = _stacking.begin(), end = _stacking.end();
618 // insert the windows above this window
619 for (; it != end; ++it) {
620 if ((*it)->layer() < layer || (raise && (*it)->layer() == layer))
621 break;
622 wins.push_back((*it)->frame->window());
623 }
624 // insert our client
625 wins.push_back(client->frame->window());
626 _stacking.insert(it, client);
627 // insert the remaining below this window
628 for (; it != end; ++it)
629 wins.push_back((*it)->frame->window());
630
631 XRestackWindows(otk::OBDisplay::display, &wins[0], wins.size());
632 changeStackingList();
633 }
634
635 void OBScreen::changeDesktop(long desktop)
636 {
637 assert(desktop >= 0 && desktop < _num_desktops);
638
639 if (!(desktop >= 0 && desktop < _num_desktops)) return;
640
641 printf("Moving to desktop %ld\n", desktop);
642
643 long old = _desktop;
644
645 _desktop = desktop;
646 Openbox::instance->property()->set(_info->rootWindow(),
647 otk::OBProperty::net_current_desktop,
648 otk::OBProperty::Atom_Cardinal,
649 _desktop);
650
651 OBClient::List::iterator it, end = clients.end();
652 for (it = clients.begin(); it != end; ++it) {
653 if ((*it)->desktop() == old) {
654 (*it)->frame->hide();
655 } else if ((*it)->desktop() == _desktop) {
656 (*it)->frame->show();
657 }
658 }
659 }
660
661 void OBScreen::changeNumDesktops(long num)
662 {
663 assert(num > 0);
664
665 if (!(num > 0)) return;
666
667 // XXX: move windows on desktops that will no longer exist!
668
669 _num_desktops = num;
670 Openbox::instance->property()->set(_info->rootWindow(),
671 otk::OBProperty::net_number_of_desktops,
672 otk::OBProperty::Atom_Cardinal,
673 _num_desktops);
674
675 // set the viewport hint
676 unsigned long *viewport = new unsigned long[_num_desktops * 2];
677 memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
678 Openbox::instance->property()->set(_info->rootWindow(),
679 otk::OBProperty::net_desktop_viewport,
680 otk::OBProperty::Atom_Cardinal,
681 viewport, _num_desktops * 2);
682 delete [] viewport;
683
684 // update the work area hint
685 changeWorkArea();
686 }
687
688
689 void OBScreen::updateDesktopNames()
690 {
691 const otk::OBProperty *property = Openbox::instance->property();
692
693 unsigned long num = (unsigned) -1;
694
695 if (!property->get(_info->rootWindow(),
696 otk::OBProperty::net_desktop_names,
697 otk::OBProperty::utf8, &num, &_desktop_names))
698 _desktop_names.clear();
699 while ((long)_desktop_names.size() < _num_desktops)
700 _desktop_names.push_back("Unnamed");
701 }
702
703
704 void OBScreen::setDesktopName(long i, const std::string &name)
705 {
706 assert(i >= 0);
707
708 if (i >= _num_desktops) return;
709
710 const otk::OBProperty *property = Openbox::instance->property();
711
712 otk::OBProperty::StringVect newnames = _desktop_names;
713 newnames[i] = name;
714 property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names,
715 otk::OBProperty::utf8, newnames);
716 }
717
718
719 void OBScreen::propertyHandler(const XPropertyEvent &e)
720 {
721 otk::OtkEventHandler::propertyHandler(e);
722
723 const otk::OBProperty *property = Openbox::instance->property();
724
725 // compress changes to a single property into a single change
726 XEvent ce;
727 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
728 // XXX: it would be nice to compress ALL changes to a property, not just
729 // changes in a row without other props between.
730 if (ce.xproperty.atom != e.atom) {
731 XPutBackEvent(otk::OBDisplay::display, &ce);
732 break;
733 }
734 }
735
736 if (e.atom == property->atom(otk::OBProperty::net_desktop_names))
737 updateDesktopNames();
738 }
739
740
741 void OBScreen::clientMessageHandler(const XClientMessageEvent &e)
742 {
743 otk::OtkEventHandler::clientMessageHandler(e);
744
745 if (e.format != 32) return;
746
747 const otk::OBProperty *property = Openbox::instance->property();
748
749 if (e.message_type == property->atom(otk::OBProperty::net_current_desktop)) {
750 changeDesktop(e.data.l[0]);
751 } else if (e.message_type ==
752 property->atom(otk::OBProperty::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 OBScreen::mapRequestHandler(const XMapRequestEvent &e)
760 {
761 otk::OtkEventHandler::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 OBClient *c = Openbox::instance->findClient(e.window);
773
774 if (c) {
775 if (c->shaded())
776 c->shade(false);
777 // XXX: uniconify the window
778 c->focus();
779 } else
780 manageWindow(e.window);
781 }
782 }
This page took 0.0742 seconds and 5 git commands to generate.