]> Dogcows Code - chaz/openbox/blob - src/screen.cc
fix \'s
[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(_number, 0, EventShutdown, 0);
144 Openbox::instance->bindings()->fireEvent(&data);
145 }
146
147
148 OBScreen::~OBScreen()
149 {
150 if (! _managed) return;
151
152 XSelectInput(otk::OBDisplay::display, _info->rootWindow(), NoEventMask);
153
154 // unmanage all windows
155 while (!clients.empty())
156 unmanageWindow(clients.front());
157
158 // call the python Shutdown callbacks
159 EventData data(_number, 0, EventShutdown, 0);
160 Openbox::instance->bindings()->fireEvent(&data);
161
162 XDestroyWindow(otk::OBDisplay::display, _focuswindow);
163 XDestroyWindow(otk::OBDisplay::display, _supportwindow);
164
165 delete _image_control;
166 }
167
168
169 void OBScreen::manageExisting()
170 {
171 unsigned int i, j, nchild;
172 Window r, p, *children;
173 XQueryTree(otk::OBDisplay::display, _info->rootWindow(), &r, &p,
174 &children, &nchild);
175
176 // preen the window list of all icon windows... for better dockapp support
177 for (i = 0; i < nchild; i++) {
178 if (children[i] == None) continue;
179
180 XWMHints *wmhints = XGetWMHints(otk::OBDisplay::display,
181 children[i]);
182
183 if (wmhints) {
184 if ((wmhints->flags & IconWindowHint) &&
185 (wmhints->icon_window != children[i])) {
186 for (j = 0; j < nchild; j++) {
187 if (children[j] == wmhints->icon_window) {
188 children[j] = None;
189 break;
190 }
191 }
192 }
193
194 XFree(wmhints);
195 }
196 }
197
198 // manage shown windows
199 for (i = 0; i < nchild; ++i) {
200 if (children[i] == None)
201 continue;
202
203 XWindowAttributes attrib;
204 if (XGetWindowAttributes(otk::OBDisplay::display, children[i], &attrib)) {
205 if (attrib.override_redirect) continue;
206
207 if (attrib.map_state != IsUnmapped) {
208 manageWindow(children[i]);
209 }
210 }
211 }
212
213 XFree(children);
214 }
215
216
217 void OBScreen::updateStrut()
218 {
219 _strut.left = _strut.right = _strut.top = _strut.bottom = 0;
220
221 OBClient::List::iterator it, end = clients.end();
222 for (it = clients.begin(); it != end; ++it) {
223 const otk::Strut &s = (*it)->strut();
224 _strut.left = std::max(_strut.left, s.left);
225 _strut.right = std::max(_strut.right, s.right);
226 _strut.top = std::max(_strut.top, s.top);
227 _strut.bottom = std::max(_strut.bottom, s.bottom);
228 }
229 calcArea();
230 }
231
232
233 void OBScreen::calcArea()
234 {
235 otk::Rect old_area = _area;
236
237 /*
238 #ifdef XINERAMA
239 // reset to the full areas
240 if (isXineramaActive())
241 xineramaUsableArea = getXineramaAreas();
242 #endif // XINERAMA
243 */
244
245 _area.setRect(_strut.left, _strut.top,
246 _info->width() - (_strut.left + _strut.right),
247 _info->height() - (_strut.top + _strut.bottom));
248
249 /*
250 #ifdef XINERAMA
251 if (isXineramaActive()) {
252 // keep each of the ximerama-defined areas inside the strut
253 RectList::iterator xit, xend = xineramaUsableArea.end();
254 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
255 if (xit->x() < usableArea.x()) {
256 xit->setX(usableArea.x());
257 xit->setWidth(xit->width() - usableArea.x());
258 }
259 if (xit->y() < usableArea.y()) {
260 xit->setY(usableArea.y());
261 xit->setHeight(xit->height() - usableArea.y());
262 }
263 if (xit->x() + xit->width() > usableArea.width())
264 xit->setWidth(usableArea.width() - xit->x());
265 if (xit->y() + xit->height() > usableArea.height())
266 xit->setHeight(usableArea.height() - xit->y());
267 }
268 }
269 #endif // XINERAMA
270 */
271
272 if (old_area != _area)
273 // XXX: re-maximize windows
274
275 changeWorkArea();
276 }
277
278
279 void OBScreen::changeSupportedAtoms()
280 {
281 // create the netwm support window
282 _supportwindow = XCreateSimpleWindow(otk::OBDisplay::display,
283 _info->rootWindow(),
284 0, 0, 1, 1, 0, 0, 0);
285
286 // set supporting window
287 Openbox::instance->property()->set(_info->rootWindow(),
288 otk::OBProperty::net_supporting_wm_check,
289 otk::OBProperty::Atom_Window,
290 _supportwindow);
291
292 //set properties on the supporting window
293 Openbox::instance->property()->set(_supportwindow,
294 otk::OBProperty::net_wm_name,
295 otk::OBProperty::utf8,
296 "Openbox");
297 Openbox::instance->property()->set(_supportwindow,
298 otk::OBProperty::net_supporting_wm_check,
299 otk::OBProperty::Atom_Window,
300 _supportwindow);
301
302
303 Atom supported[] = {
304 otk::OBProperty::net_current_desktop,
305 otk::OBProperty::net_number_of_desktops,
306 otk::OBProperty::net_desktop_geometry,
307 otk::OBProperty::net_desktop_viewport,
308 otk::OBProperty::net_active_window,
309 otk::OBProperty::net_workarea,
310 otk::OBProperty::net_client_list,
311 otk::OBProperty::net_client_list_stacking,
312 otk::OBProperty::net_desktop_names,
313 otk::OBProperty::net_close_window,
314 otk::OBProperty::net_wm_name,
315 otk::OBProperty::net_wm_visible_name,
316 otk::OBProperty::net_wm_icon_name,
317 otk::OBProperty::net_wm_visible_icon_name,
318 /*
319 otk::OBProperty::net_wm_desktop,
320 */
321 otk::OBProperty::net_wm_strut,
322 otk::OBProperty::net_wm_window_type,
323 otk::OBProperty::net_wm_window_type_desktop,
324 otk::OBProperty::net_wm_window_type_dock,
325 otk::OBProperty::net_wm_window_type_toolbar,
326 otk::OBProperty::net_wm_window_type_menu,
327 otk::OBProperty::net_wm_window_type_utility,
328 otk::OBProperty::net_wm_window_type_splash,
329 otk::OBProperty::net_wm_window_type_dialog,
330 otk::OBProperty::net_wm_window_type_normal,
331 /*
332 otk::OBProperty::net_wm_moveresize,
333 otk::OBProperty::net_wm_moveresize_size_topleft,
334 otk::OBProperty::net_wm_moveresize_size_topright,
335 otk::OBProperty::net_wm_moveresize_size_bottomleft,
336 otk::OBProperty::net_wm_moveresize_size_bottomright,
337 otk::OBProperty::net_wm_moveresize_move,
338 */
339 /*
340 otk::OBProperty::net_wm_allowed_actions,
341 otk::OBProperty::net_wm_action_move,
342 otk::OBProperty::net_wm_action_resize,
343 otk::OBProperty::net_wm_action_shade,
344 otk::OBProperty::net_wm_action_maximize_horz,
345 otk::OBProperty::net_wm_action_maximize_vert,
346 otk::OBProperty::net_wm_action_change_desktop,
347 otk::OBProperty::net_wm_action_close,
348 */
349 otk::OBProperty::net_wm_state,
350 otk::OBProperty::net_wm_state_modal,
351 otk::OBProperty::net_wm_state_maximized_vert,
352 otk::OBProperty::net_wm_state_maximized_horz,
353 otk::OBProperty::net_wm_state_shaded,
354 otk::OBProperty::net_wm_state_skip_taskbar,
355 otk::OBProperty::net_wm_state_skip_pager,
356 otk::OBProperty::net_wm_state_hidden,
357 otk::OBProperty::net_wm_state_fullscreen,
358 otk::OBProperty::net_wm_state_above,
359 otk::OBProperty::net_wm_state_below,
360 };
361 const int num_supported = sizeof(supported)/sizeof(Atom);
362
363 // convert to the atom values
364 for (int i = 0; i < num_supported; ++i)
365 supported[i] =
366 Openbox::instance->property()->atom((otk::OBProperty::Atoms)supported[i]);
367
368 Openbox::instance->property()->set(_info->rootWindow(),
369 otk::OBProperty::net_supported,
370 otk::OBProperty::Atom_Atom,
371 supported, num_supported);
372 }
373
374
375 void OBScreen::changeClientList()
376 {
377 Window *windows;
378 unsigned int size = clients.size();
379
380 // create an array of the window ids
381 if (size > 0) {
382 Window *win_it;
383
384 windows = new Window[size];
385 win_it = windows;
386 OBClient::List::const_iterator it = clients.begin();
387 const OBClient::List::const_iterator end = clients.end();
388 for (; it != end; ++it, ++win_it)
389 *win_it = (*it)->window();
390 } else
391 windows = (Window*) 0;
392
393 Openbox::instance->property()->set(_info->rootWindow(),
394 otk::OBProperty::net_client_list,
395 otk::OBProperty::Atom_Window,
396 windows, size);
397
398 if (size)
399 delete [] windows;
400
401 changeStackingList();
402 }
403
404
405 void OBScreen::changeStackingList()
406 {
407 Window *windows;
408 unsigned int size = _stacking.size();
409
410 assert(size == clients.size()); // just making sure.. :)
411
412
413 // create an array of the window ids
414 if (size > 0) {
415 Window *win_it;
416
417 windows = new Window[size];
418 win_it = windows;
419 OBClient::List::const_iterator it = _stacking.begin();
420 const OBClient::List::const_iterator end = _stacking.end();
421 for (; it != end; ++it, ++win_it)
422 *win_it = (*it)->window();
423 } else
424 windows = (Window*) 0;
425
426 Openbox::instance->property()->set(_info->rootWindow(),
427 otk::OBProperty::net_client_list_stacking,
428 otk::OBProperty::Atom_Window,
429 windows, size);
430
431 if (size)
432 delete [] windows;
433 }
434
435
436 void OBScreen::changeWorkArea() {
437 unsigned long *dims = new unsigned long[4 * _num_desktops];
438 for (long i = 0; i < _num_desktops; ++i) {
439 // XXX: this could be different for each workspace
440 dims[(i * 4) + 0] = _area.x();
441 dims[(i * 4) + 1] = _area.y();
442 dims[(i * 4) + 2] = _area.width();
443 dims[(i * 4) + 3] = _area.height();
444 }
445 Openbox::instance->property()->set(_info->rootWindow(),
446 otk::OBProperty::net_workarea,
447 otk::OBProperty::Atom_Cardinal,
448 dims, 4 * _num_desktops);
449 delete [] dims;
450 }
451
452
453 void OBScreen::manageWindow(Window window)
454 {
455 OBClient *client = 0;
456 XWMHints *wmhint;
457 XSetWindowAttributes attrib_set;
458
459 otk::OBDisplay::grab();
460
461 // is the window a docking app
462 if ((wmhint = XGetWMHints(otk::OBDisplay::display, window))) {
463 if ((wmhint->flags & StateHint) &&
464 wmhint->initial_state == WithdrawnState) {
465 //slit->addClient(w); // XXX: make dock apps work!
466 otk::OBDisplay::ungrab();
467
468 XFree(wmhint);
469 return;
470 }
471 XFree(wmhint);
472 }
473
474 // choose the events we want to receive on the CLIENT window
475 attrib_set.event_mask = OBClient::event_mask;
476 attrib_set.do_not_propagate_mask = OBClient::no_propagate_mask;
477 XChangeWindowAttributes(otk::OBDisplay::display, window,
478 CWEventMask|CWDontPropagate, &attrib_set);
479
480 // create the OBClient class, which gets all of the hints on the window
481 client = new OBClient(_number, window);
482 // register for events
483 Openbox::instance->registerHandler(window, client);
484 // add to the wm's map
485 Openbox::instance->addClient(window, client);
486
487 // we dont want a border on the client
488 client->toggleClientBorder(false);
489
490 // specify that if we exit, the window should not be destroyed and should be
491 // reparented back to root automatically
492 XChangeSaveSet(otk::OBDisplay::display, window, SetModeInsert);
493
494 if (!(Openbox::instance->state() == Openbox::State_Starting ||
495 client->positionRequested())) {
496 // position the window intelligenty .. hopefully :)
497 // call the python PLACEWINDOW binding
498 EventData data(_number, client, EventPlaceWindow, 0);
499 Openbox::instance->bindings()->fireEvent(&data);
500 }
501
502 // create the decoration frame for the client window
503 client->frame = new OBFrame(client, &_style);
504
505 // add to the wm's map
506 Openbox::instance->addClient(client->frame->window(), client);
507 Openbox::instance->addClient(client->frame->plate(), client);
508 Openbox::instance->addClient(client->frame->titlebar(), client);
509 Openbox::instance->addClient(client->frame->label(), client);
510 Openbox::instance->addClient(client->frame->button_max(), client);
511 Openbox::instance->addClient(client->frame->button_iconify(), client);
512 Openbox::instance->addClient(client->frame->button_stick(), client);
513 Openbox::instance->addClient(client->frame->button_close(), client);
514 Openbox::instance->addClient(client->frame->handle(), client);
515 Openbox::instance->addClient(client->frame->grip_left(), client);
516 Openbox::instance->addClient(client->frame->grip_right(), client);
517
518 // reparent the client to the frame
519 client->frame->grabClient();
520
521 // if on the current desktop.. (or all desktops)
522 if (client->desktop() == _desktop ||
523 client->desktop() == (signed)0xffffffff) {
524 client->frame->show();
525 }
526
527 // XXX: handle any requested states such as maximized
528
529 otk::OBDisplay::ungrab();
530
531 // add to the screen's list
532 clients.push_back(client);
533 // this puts into the stacking order, then raises it
534 _stacking.push_back(client);
535 restack(true, client);
536 // update the root properties
537 changeClientList();
538
539 Openbox::instance->bindings()->grabButtons(true, client);
540
541 // call the python NEWWINDOW binding
542 EventData data(_number, client, EventNewWindow, 0);
543 Openbox::instance->bindings()->fireEvent(&data);
544
545 #ifdef DEBUG
546 printf("Managed window 0x%lx\n", window);
547 #endif
548 }
549
550
551 void OBScreen::unmanageWindow(OBClient *client)
552 {
553 OBFrame *frame = client->frame;
554
555 // call the python CLOSEWINDOW binding
556 EventData data(_number, client, EventCloseWindow, 0);
557 Openbox::instance->bindings()->fireEvent(&data);
558
559 Openbox::instance->bindings()->grabButtons(false, client);
560
561 // remove from the wm's map
562 Openbox::instance->removeClient(client->window());
563 Openbox::instance->removeClient(frame->window());
564 Openbox::instance->removeClient(frame->plate());
565 Openbox::instance->removeClient(frame->titlebar());
566 Openbox::instance->removeClient(frame->label());
567 Openbox::instance->removeClient(frame->button_max());
568 Openbox::instance->removeClient(frame->button_iconify());
569 Openbox::instance->removeClient(frame->button_stick());
570 Openbox::instance->removeClient(frame->button_close());
571 Openbox::instance->removeClient(frame->handle());
572 Openbox::instance->removeClient(frame->grip_left());
573 Openbox::instance->removeClient(frame->grip_right());
574 // unregister for handling events
575 Openbox::instance->clearHandler(client->window());
576
577 // remove the window from our save set
578 XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
579
580 // we dont want events no more
581 XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
582
583 frame->hide();
584
585 // give the client its border back
586 client->toggleClientBorder(true);
587
588 // reparent the window out of the frame
589 frame->releaseClient();
590
591 delete client->frame;
592 client->frame = 0;
593
594 // remove from the stacking order
595 _stacking.remove(client);
596
597 // remove from the screen's list
598 clients.remove(client);
599
600 // unfocus the client (calls the focus callbacks)
601 client->unfocus();
602
603 #ifdef DEBUG
604 printf("Unmanaged window 0x%lx\n", client->window());
605 #endif
606
607 delete client;
608
609 // update the root properties
610 changeClientList();
611 }
612
613 void OBScreen::restack(bool raise, OBClient *client)
614 {
615 const int layer = client->layer();
616 std::vector<Window> wins;
617
618 _stacking.remove(client);
619
620 // the stacking list is from highest to lowest
621
622 OBClient::List::iterator it = _stacking.begin(), end = _stacking.end();
623 // insert the windows above this window
624 for (; it != end; ++it) {
625 if ((*it)->layer() < layer || (raise && (*it)->layer() == layer))
626 break;
627 wins.push_back((*it)->frame->window());
628 }
629 // insert our client
630 wins.push_back(client->frame->window());
631 _stacking.insert(it, client);
632 // insert the remaining below this window
633 for (; it != end; ++it)
634 wins.push_back((*it)->frame->window());
635
636 XRestackWindows(otk::OBDisplay::display, &wins[0], wins.size());
637 changeStackingList();
638 }
639
640 void OBScreen::changeDesktop(long desktop)
641 {
642 assert(desktop >= 0 && desktop < _num_desktops);
643
644 if (!(desktop >= 0 && desktop < _num_desktops)) return;
645
646 printf("Moving to desktop %ld\n", desktop);
647
648 long old = _desktop;
649
650 _desktop = desktop;
651 Openbox::instance->property()->set(_info->rootWindow(),
652 otk::OBProperty::net_current_desktop,
653 otk::OBProperty::Atom_Cardinal,
654 _desktop);
655
656 if (old == _desktop) return;
657
658 OBClient::List::iterator it, end = clients.end();
659 for (it = clients.begin(); it != end; ++it) {
660 if ((*it)->desktop() == old) {
661 (*it)->frame->hide();
662 } else if ((*it)->desktop() == _desktop) {
663 (*it)->frame->show();
664 }
665 }
666
667 // force the callbacks to fire
668 if (!Openbox::instance->focusedClient())
669 Openbox::instance->setFocusedClient(0);
670 }
671
672 void OBScreen::changeNumDesktops(long num)
673 {
674 assert(num > 0);
675
676 if (!(num > 0)) return;
677
678 // XXX: move windows on desktops that will no longer exist!
679
680 _num_desktops = num;
681 Openbox::instance->property()->set(_info->rootWindow(),
682 otk::OBProperty::net_number_of_desktops,
683 otk::OBProperty::Atom_Cardinal,
684 _num_desktops);
685
686 // set the viewport hint
687 unsigned long *viewport = new unsigned long[_num_desktops * 2];
688 memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
689 Openbox::instance->property()->set(_info->rootWindow(),
690 otk::OBProperty::net_desktop_viewport,
691 otk::OBProperty::Atom_Cardinal,
692 viewport, _num_desktops * 2);
693 delete [] viewport;
694
695 // update the work area hint
696 changeWorkArea();
697 }
698
699
700 void OBScreen::updateDesktopNames()
701 {
702 const otk::OBProperty *property = Openbox::instance->property();
703
704 unsigned long num = (unsigned) -1;
705
706 if (!property->get(_info->rootWindow(),
707 otk::OBProperty::net_desktop_names,
708 otk::OBProperty::utf8, &num, &_desktop_names))
709 _desktop_names.clear();
710 while ((long)_desktop_names.size() < _num_desktops)
711 _desktop_names.push_back("Unnamed");
712 }
713
714
715 void OBScreen::setDesktopName(long i, const std::string &name)
716 {
717 assert(i >= 0);
718
719 if (i >= _num_desktops) return;
720
721 const otk::OBProperty *property = Openbox::instance->property();
722
723 otk::OBProperty::StringVect newnames = _desktop_names;
724 newnames[i] = name;
725 property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names,
726 otk::OBProperty::utf8, newnames);
727 }
728
729
730 void OBScreen::propertyHandler(const XPropertyEvent &e)
731 {
732 otk::OtkEventHandler::propertyHandler(e);
733
734 const otk::OBProperty *property = Openbox::instance->property();
735
736 // compress changes to a single property into a single change
737 XEvent ce;
738 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
739 // XXX: it would be nice to compress ALL changes to a property, not just
740 // changes in a row without other props between.
741 if (ce.xproperty.atom != e.atom) {
742 XPutBackEvent(otk::OBDisplay::display, &ce);
743 break;
744 }
745 }
746
747 if (e.atom == property->atom(otk::OBProperty::net_desktop_names))
748 updateDesktopNames();
749 }
750
751
752 void OBScreen::clientMessageHandler(const XClientMessageEvent &e)
753 {
754 otk::OtkEventHandler::clientMessageHandler(e);
755
756 if (e.format != 32) return;
757
758 const otk::OBProperty *property = Openbox::instance->property();
759
760 if (e.message_type == property->atom(otk::OBProperty::net_current_desktop)) {
761 changeDesktop(e.data.l[0]);
762 } else if (e.message_type ==
763 property->atom(otk::OBProperty::net_number_of_desktops)) {
764 changeNumDesktops(e.data.l[0]);
765 }
766 // XXX: so many client messages to handle here! ..or not.. they go to clients
767 }
768
769
770 void OBScreen::mapRequestHandler(const XMapRequestEvent &e)
771 {
772 otk::OtkEventHandler::mapRequestHandler(e);
773
774 #ifdef DEBUG
775 printf("MapRequest for 0x%lx\n", e.window);
776 #endif // DEBUG
777
778 /*
779 MapRequest events come here even after the window exists instead of going
780 right to the client window, because of how they are sent and their struct
781 layout.
782 */
783 OBClient *c = Openbox::instance->findClient(e.window);
784
785 if (c) {
786 // send a net_active_window message
787 XEvent ce;
788 ce.xclient.type = ClientMessage;
789 ce.xclient.message_type =
790 Openbox::instance->property()->atom(otk::OBProperty::net_active_window);
791 ce.xclient.display = otk::OBDisplay::display;
792 ce.xclient.window = c->window();
793 ce.xclient.format = 32;
794 ce.xclient.data.l[0] = 0l;
795 ce.xclient.data.l[1] = 0l;
796 ce.xclient.data.l[2] = 0l;
797 ce.xclient.data.l[3] = 0l;
798 ce.xclient.data.l[4] = 0l;
799 XSendEvent(otk::OBDisplay::display, _info->rootWindow(), false,
800 SubstructureRedirectMask | SubstructureNotifyMask,
801 &ce);
802 } else
803 manageWindow(e.window);
804 }
805 }
This page took 0.073392 seconds and 4 git commands to generate.