]> Dogcows Code - chaz/openbox/blob - src/screen.cc
sending windows to workspaces works. focus messes up on fast switching
[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 // call the python Startup callbacks
143 EventData *data = new_event_data(_number, 0, EventShutdown, 0);
144 Openbox::instance->bindings()->fireEvent(data);
145 Py_XDECREF((PyObject*)data);
146 }
147
148
149 OBScreen::~OBScreen()
150 {
151 if (! _managed) return;
152
153 XSelectInput(otk::OBDisplay::display, _info->rootWindow(), NoEventMask);
154
155 // unmanage all windows
156 while (!clients.empty())
157 unmanageWindow(clients.front());
158
159 // call the python Shutdown callbacks
160 EventData *data = new_event_data(_number, 0, EventShutdown, 0);
161 Openbox::instance->bindings()->fireEvent(data);
162 Py_XDECREF((PyObject*)data);
163
164 XDestroyWindow(otk::OBDisplay::display, _focuswindow);
165 XDestroyWindow(otk::OBDisplay::display, _supportwindow);
166
167 delete _image_control;
168 }
169
170
171 void OBScreen::manageExisting()
172 {
173 unsigned int i, j, nchild;
174 Window r, p, *children;
175 XQueryTree(otk::OBDisplay::display, _info->rootWindow(), &r, &p,
176 &children, &nchild);
177
178 // preen the window list of all icon windows... for better dockapp support
179 for (i = 0; i < nchild; i++) {
180 if (children[i] == None) continue;
181
182 XWMHints *wmhints = XGetWMHints(otk::OBDisplay::display,
183 children[i]);
184
185 if (wmhints) {
186 if ((wmhints->flags & IconWindowHint) &&
187 (wmhints->icon_window != children[i])) {
188 for (j = 0; j < nchild; j++) {
189 if (children[j] == wmhints->icon_window) {
190 children[j] = None;
191 break;
192 }
193 }
194 }
195
196 XFree(wmhints);
197 }
198 }
199
200 // manage shown windows
201 for (i = 0; i < nchild; ++i) {
202 if (children[i] == None)
203 continue;
204
205 XWindowAttributes attrib;
206 if (XGetWindowAttributes(otk::OBDisplay::display, children[i], &attrib)) {
207 if (attrib.override_redirect) continue;
208
209 if (attrib.map_state != IsUnmapped) {
210 manageWindow(children[i]);
211 }
212 }
213 }
214
215 XFree(children);
216 }
217
218
219 void OBScreen::updateStrut()
220 {
221 _strut.left = _strut.right = _strut.top = _strut.bottom = 0;
222
223 OBClient::List::iterator it, end = clients.end();
224 for (it = clients.begin(); it != end; ++it) {
225 const otk::Strut &s = (*it)->strut();
226 _strut.left = std::max(_strut.left, s.left);
227 _strut.right = std::max(_strut.right, s.right);
228 _strut.top = std::max(_strut.top, s.top);
229 _strut.bottom = std::max(_strut.bottom, s.bottom);
230 }
231 calcArea();
232 }
233
234
235 void OBScreen::calcArea()
236 {
237 otk::Rect old_area = _area;
238
239 /*
240 #ifdef XINERAMA
241 // reset to the full areas
242 if (isXineramaActive())
243 xineramaUsableArea = getXineramaAreas();
244 #endif // XINERAMA
245 */
246
247 _area.setRect(_strut.left, _strut.top,
248 _info->width() - (_strut.left + _strut.right),
249 _info->height() - (_strut.top + _strut.bottom));
250
251 /*
252 #ifdef XINERAMA
253 if (isXineramaActive()) {
254 // keep each of the ximerama-defined areas inside the strut
255 RectList::iterator xit, xend = xineramaUsableArea.end();
256 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
257 if (xit->x() < usableArea.x()) {
258 xit->setX(usableArea.x());
259 xit->setWidth(xit->width() - usableArea.x());
260 }
261 if (xit->y() < usableArea.y()) {
262 xit->setY(usableArea.y());
263 xit->setHeight(xit->height() - usableArea.y());
264 }
265 if (xit->x() + xit->width() > usableArea.width())
266 xit->setWidth(usableArea.width() - xit->x());
267 if (xit->y() + xit->height() > usableArea.height())
268 xit->setHeight(usableArea.height() - xit->y());
269 }
270 }
271 #endif // XINERAMA
272 */
273
274 if (old_area != _area)
275 // XXX: re-maximize windows
276
277 changeWorkArea();
278 }
279
280
281 void OBScreen::changeSupportedAtoms()
282 {
283 // create the netwm support window
284 _supportwindow = XCreateSimpleWindow(otk::OBDisplay::display,
285 _info->rootWindow(),
286 0, 0, 1, 1, 0, 0, 0);
287 assert(_supportwindow != None);
288
289 // set supporting window
290 Openbox::instance->property()->set(_info->rootWindow(),
291 otk::OBProperty::net_supporting_wm_check,
292 otk::OBProperty::Atom_Window,
293 _supportwindow);
294
295 //set properties on the supporting window
296 Openbox::instance->property()->set(_supportwindow,
297 otk::OBProperty::net_wm_name,
298 otk::OBProperty::utf8,
299 "Openbox");
300 Openbox::instance->property()->set(_supportwindow,
301 otk::OBProperty::net_supporting_wm_check,
302 otk::OBProperty::Atom_Window,
303 _supportwindow);
304
305
306 Atom supported[] = {
307 otk::OBProperty::net_current_desktop,
308 otk::OBProperty::net_number_of_desktops,
309 otk::OBProperty::net_desktop_geometry,
310 otk::OBProperty::net_desktop_viewport,
311 otk::OBProperty::net_active_window,
312 otk::OBProperty::net_workarea,
313 otk::OBProperty::net_client_list,
314 otk::OBProperty::net_client_list_stacking,
315 otk::OBProperty::net_desktop_names,
316 otk::OBProperty::net_close_window,
317 otk::OBProperty::net_wm_name,
318 otk::OBProperty::net_wm_visible_name,
319 otk::OBProperty::net_wm_icon_name,
320 otk::OBProperty::net_wm_visible_icon_name,
321 /*
322 otk::OBProperty::net_wm_desktop,
323 */
324 otk::OBProperty::net_wm_strut,
325 otk::OBProperty::net_wm_window_type,
326 otk::OBProperty::net_wm_window_type_desktop,
327 otk::OBProperty::net_wm_window_type_dock,
328 otk::OBProperty::net_wm_window_type_toolbar,
329 otk::OBProperty::net_wm_window_type_menu,
330 otk::OBProperty::net_wm_window_type_utility,
331 otk::OBProperty::net_wm_window_type_splash,
332 otk::OBProperty::net_wm_window_type_dialog,
333 otk::OBProperty::net_wm_window_type_normal,
334 /*
335 otk::OBProperty::net_wm_moveresize,
336 otk::OBProperty::net_wm_moveresize_size_topleft,
337 otk::OBProperty::net_wm_moveresize_size_topright,
338 otk::OBProperty::net_wm_moveresize_size_bottomleft,
339 otk::OBProperty::net_wm_moveresize_size_bottomright,
340 otk::OBProperty::net_wm_moveresize_move,
341 */
342 /*
343 otk::OBProperty::net_wm_allowed_actions,
344 otk::OBProperty::net_wm_action_move,
345 otk::OBProperty::net_wm_action_resize,
346 otk::OBProperty::net_wm_action_shade,
347 otk::OBProperty::net_wm_action_maximize_horz,
348 otk::OBProperty::net_wm_action_maximize_vert,
349 otk::OBProperty::net_wm_action_change_desktop,
350 otk::OBProperty::net_wm_action_close,
351 */
352 otk::OBProperty::net_wm_state,
353 otk::OBProperty::net_wm_state_modal,
354 otk::OBProperty::net_wm_state_maximized_vert,
355 otk::OBProperty::net_wm_state_maximized_horz,
356 otk::OBProperty::net_wm_state_shaded,
357 otk::OBProperty::net_wm_state_skip_taskbar,
358 otk::OBProperty::net_wm_state_skip_pager,
359 otk::OBProperty::net_wm_state_hidden,
360 otk::OBProperty::net_wm_state_fullscreen,
361 otk::OBProperty::net_wm_state_above,
362 otk::OBProperty::net_wm_state_below,
363 };
364 const int num_supported = sizeof(supported)/sizeof(Atom);
365
366 // convert to the atom values
367 for (int i = 0; i < num_supported; ++i)
368 supported[i] =
369 Openbox::instance->property()->atom((otk::OBProperty::Atoms)supported[i]);
370
371 Openbox::instance->property()->set(_info->rootWindow(),
372 otk::OBProperty::net_supported,
373 otk::OBProperty::Atom_Atom,
374 supported, num_supported);
375 }
376
377
378 void OBScreen::changeClientList()
379 {
380 Window *windows;
381 unsigned int size = clients.size();
382
383 // create an array of the window ids
384 if (size > 0) {
385 Window *win_it;
386
387 windows = new Window[size];
388 win_it = windows;
389 OBClient::List::const_iterator it = clients.begin();
390 const OBClient::List::const_iterator end = clients.end();
391 for (; it != end; ++it, ++win_it)
392 *win_it = (*it)->window();
393 } else
394 windows = (Window*) 0;
395
396 Openbox::instance->property()->set(_info->rootWindow(),
397 otk::OBProperty::net_client_list,
398 otk::OBProperty::Atom_Window,
399 windows, size);
400
401 if (size)
402 delete [] windows;
403
404 changeStackingList();
405 }
406
407
408 void OBScreen::changeStackingList()
409 {
410 Window *windows;
411 unsigned int size = _stacking.size();
412
413 assert(size == clients.size()); // just making sure.. :)
414
415
416 // create an array of the window ids
417 if (size > 0) {
418 Window *win_it;
419
420 windows = new Window[size];
421 win_it = windows;
422 OBClient::List::const_iterator it = _stacking.begin();
423 const OBClient::List::const_iterator end = _stacking.end();
424 for (; it != end; ++it, ++win_it)
425 *win_it = (*it)->window();
426 } else
427 windows = (Window*) 0;
428
429 Openbox::instance->property()->set(_info->rootWindow(),
430 otk::OBProperty::net_client_list_stacking,
431 otk::OBProperty::Atom_Window,
432 windows, size);
433
434 if (size)
435 delete [] windows;
436 }
437
438
439 void OBScreen::changeWorkArea() {
440 unsigned long *dims = new unsigned long[4 * _num_desktops];
441 for (long i = 0; i < _num_desktops; ++i) {
442 // XXX: this could be different for each workspace
443 dims[(i * 4) + 0] = _area.x();
444 dims[(i * 4) + 1] = _area.y();
445 dims[(i * 4) + 2] = _area.width();
446 dims[(i * 4) + 3] = _area.height();
447 }
448 Openbox::instance->property()->set(_info->rootWindow(),
449 otk::OBProperty::net_workarea,
450 otk::OBProperty::Atom_Cardinal,
451 dims, 4 * _num_desktops);
452 delete [] dims;
453 }
454
455
456 void OBScreen::manageWindow(Window window)
457 {
458 OBClient *client = 0;
459 XWMHints *wmhint;
460 XSetWindowAttributes attrib_set;
461
462 // is the window a docking app
463 if ((wmhint = XGetWMHints(otk::OBDisplay::display, window))) {
464 if ((wmhint->flags & StateHint) &&
465 wmhint->initial_state == WithdrawnState) {
466 //slit->addClient(w); // XXX: make dock apps work!
467 XFree(wmhint);
468 return;
469 }
470 XFree(wmhint);
471 }
472
473 otk::OBDisplay::grab();
474
475 // choose the events we want to receive on the CLIENT window
476 attrib_set.event_mask = OBClient::event_mask;
477 attrib_set.do_not_propagate_mask = OBClient::no_propagate_mask;
478 XChangeWindowAttributes(otk::OBDisplay::display, window,
479 CWEventMask|CWDontPropagate, &attrib_set);
480
481 // create the OBClient class, which gets all of the hints on the window
482 client = new OBClient(_number, window);
483 // register for events
484 Openbox::instance->registerHandler(window, client);
485 // add to the wm's map
486 Openbox::instance->addClient(window, client);
487
488 // we dont want a border on the client
489 client->toggleClientBorder(false);
490
491 // specify that if we exit, the window should not be destroyed and should be
492 // reparented back to root automatically
493 XChangeSaveSet(otk::OBDisplay::display, window, SetModeInsert);
494
495 if (!client->positionRequested()) {
496 // XXX: position the window intelligenty
497 }
498
499 // create the decoration frame for the client window
500 client->frame = new OBFrame(client, &_style);
501
502 // add to the wm's map
503 Openbox::instance->addClient(client->frame->window(), client);
504 Openbox::instance->addClient(client->frame->plate(), client);
505 Openbox::instance->addClient(client->frame->titlebar(), client);
506 Openbox::instance->addClient(client->frame->label(), client);
507 Openbox::instance->addClient(client->frame->button_max(), client);
508 Openbox::instance->addClient(client->frame->button_iconify(), client);
509 Openbox::instance->addClient(client->frame->button_stick(), client);
510 Openbox::instance->addClient(client->frame->button_close(), client);
511 Openbox::instance->addClient(client->frame->handle(), client);
512 Openbox::instance->addClient(client->frame->grip_left(), client);
513 Openbox::instance->addClient(client->frame->grip_right(), client);
514
515 bool shown = false;
516
517 // if on the current desktop.. (or all desktops)
518 if (client->desktop() == _desktop ||
519 client->desktop() == (signed)0xffffffff) {
520 shown = true;
521 client->frame->show();
522 }
523
524 // XXX: handle any requested states such as maximized
525
526 otk::OBDisplay::ungrab();
527
528 // add to the screen's list
529 clients.push_back(client);
530 // this puts into the stacking order, then raises it
531 _stacking.push_back(client);
532 restack(true, client);
533 // update the root properties
534 changeClientList();
535
536 Openbox::instance->bindings()->grabButtons(true, client);
537
538 // call the python NEWWINDOW binding
539 EventData *data = new_event_data(_number, window, EventNewWindow, 0);
540 Openbox::instance->bindings()->fireEvent(data);
541 Py_DECREF((PyObject*)data);
542
543 printf("Managed window 0x%lx\n", window);
544 }
545
546
547 void OBScreen::unmanageWindow(OBClient *client)
548 {
549 OBFrame *frame = client->frame;
550
551 // call the python CLOSEWINDOW binding
552 EventData *data = new_event_data(_number, client->window(),
553 EventCloseWindow, 0);
554 Openbox::instance->bindings()->fireEvent(data);
555 Py_DECREF((PyObject*)data);
556
557 Openbox::instance->bindings()->grabButtons(false, client);
558
559 // remove from the stacking order
560 _stacking.remove(client);
561
562 // unfocus the client
563 client->unfocus();
564
565 // remove from the wm's map
566 Openbox::instance->removeClient(client->window());
567 Openbox::instance->removeClient(frame->window());
568 Openbox::instance->removeClient(frame->plate());
569 Openbox::instance->removeClient(frame->titlebar());
570 Openbox::instance->removeClient(frame->label());
571 Openbox::instance->removeClient(frame->button_max());
572 Openbox::instance->removeClient(frame->button_iconify());
573 Openbox::instance->removeClient(frame->button_stick());
574 Openbox::instance->removeClient(frame->button_close());
575 Openbox::instance->removeClient(frame->handle());
576 Openbox::instance->removeClient(frame->grip_left());
577 Openbox::instance->removeClient(frame->grip_right());
578 // unregister for handling events
579 Openbox::instance->clearHandler(client->window());
580
581 // remove the window from our save set
582 XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
583
584 // we dont want events no more
585 XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
586
587 frame->hide();
588
589 // give the client its border back
590 client->toggleClientBorder(true);
591
592 delete client->frame;
593 client->frame = 0;
594
595 // remove from the screen's list
596 clients.remove(client);
597 delete client;
598
599 // update the root properties
600 changeClientList();
601 }
602
603 void OBScreen::restack(bool raise, OBClient *client)
604 {
605 const int layer = client->layer();
606 std::vector<Window> wins;
607
608 _stacking.remove(client);
609
610 // the stacking list is from highest to lowest
611
612 OBClient::List::iterator it = _stacking.begin(), end = _stacking.end();
613 // insert the windows above this window
614 for (; it != end; ++it) {
615 if ((*it)->layer() < layer || (raise && (*it)->layer() == layer))
616 break;
617 wins.push_back((*it)->frame->window());
618 }
619 // insert our client
620 wins.push_back(client->frame->window());
621 _stacking.insert(it, client);
622 // insert the remaining below this window
623 for (; it != end; ++it)
624 wins.push_back((*it)->frame->window());
625
626 XRestackWindows(otk::OBDisplay::display, &wins[0], wins.size());
627 changeStackingList();
628 }
629
630 void OBScreen::changeDesktop(long desktop)
631 {
632 assert(desktop >= 0 && desktop < _num_desktops);
633
634 if (!(desktop >= 0 && desktop < _num_desktops)) return;
635
636 printf("Moving to desktop %ld\n", desktop);
637
638 long old = _desktop;
639
640 _desktop = desktop;
641 Openbox::instance->property()->set(_info->rootWindow(),
642 otk::OBProperty::net_current_desktop,
643 otk::OBProperty::Atom_Cardinal,
644 _desktop);
645
646 if (old == _desktop) return;
647
648 OBClient::List::iterator it, end = clients.end();
649 for (it = clients.begin(); it != end; ++it) {
650 if ((*it)->desktop() == old) {
651 (*it)->frame->hide();
652 } else if ((*it)->desktop() == _desktop) {
653 (*it)->frame->show();
654 }
655 }
656
657 // force the callbacks to fire
658 Openbox::instance->setFocusedClient(0);
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.07063 seconds and 5 git commands to generate.