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