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