]> Dogcows Code - chaz/openbox/blob - src/screen.cc
don't place the window magically if we're starting (the window was already placed)
[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 (!(Openbox::instance->state() == Openbox::State_Starting ||
496 client->positionRequested())) {
497 // position the window intelligenty .. hopefully :)
498 // call the python PLACEWINDOW binding
499 EventData *data = new_event_data(_number, window, EventPlaceWindow, 0);
500 Openbox::instance->bindings()->fireEvent(data);
501 Py_DECREF((PyObject*)data);
502 }
503
504 // create the decoration frame for the client window
505 client->frame = new OBFrame(client, &_style);
506
507 // add to the wm's map
508 Openbox::instance->addClient(client->frame->window(), client);
509 Openbox::instance->addClient(client->frame->plate(), client);
510 Openbox::instance->addClient(client->frame->titlebar(), client);
511 Openbox::instance->addClient(client->frame->label(), client);
512 Openbox::instance->addClient(client->frame->button_max(), client);
513 Openbox::instance->addClient(client->frame->button_iconify(), client);
514 Openbox::instance->addClient(client->frame->button_stick(), client);
515 Openbox::instance->addClient(client->frame->button_close(), client);
516 Openbox::instance->addClient(client->frame->handle(), client);
517 Openbox::instance->addClient(client->frame->grip_left(), client);
518 Openbox::instance->addClient(client->frame->grip_right(), client);
519
520 bool shown = false;
521
522 // if on the current desktop.. (or all desktops)
523 if (client->desktop() == _desktop ||
524 client->desktop() == (signed)0xffffffff) {
525 shown = true;
526 client->frame->show();
527 }
528
529 // XXX: handle any requested states such as maximized
530
531 otk::OBDisplay::ungrab();
532
533 // add to the screen's list
534 clients.push_back(client);
535 // this puts into the stacking order, then raises it
536 _stacking.push_back(client);
537 restack(true, client);
538 // update the root properties
539 changeClientList();
540
541 Openbox::instance->bindings()->grabButtons(true, client);
542
543 // call the python NEWWINDOW binding
544 EventData *data = new_event_data(_number, window, EventNewWindow, 0);
545 Openbox::instance->bindings()->fireEvent(data);
546 Py_DECREF((PyObject*)data);
547
548 printf("Managed window 0x%lx\n", window);
549 }
550
551
552 void OBScreen::unmanageWindow(OBClient *client)
553 {
554 OBFrame *frame = client->frame;
555
556 // call the python CLOSEWINDOW binding
557 EventData *data = new_event_data(_number, client->window(),
558 EventCloseWindow, 0);
559 Openbox::instance->bindings()->fireEvent(data);
560 Py_DECREF((PyObject*)data);
561
562 Openbox::instance->bindings()->grabButtons(false, client);
563
564 // remove from the wm's map
565 Openbox::instance->removeClient(client->window());
566 Openbox::instance->removeClient(frame->window());
567 Openbox::instance->removeClient(frame->plate());
568 Openbox::instance->removeClient(frame->titlebar());
569 Openbox::instance->removeClient(frame->label());
570 Openbox::instance->removeClient(frame->button_max());
571 Openbox::instance->removeClient(frame->button_iconify());
572 Openbox::instance->removeClient(frame->button_stick());
573 Openbox::instance->removeClient(frame->button_close());
574 Openbox::instance->removeClient(frame->handle());
575 Openbox::instance->removeClient(frame->grip_left());
576 Openbox::instance->removeClient(frame->grip_right());
577 // unregister for handling events
578 Openbox::instance->clearHandler(client->window());
579
580 // remove the window from our save set
581 XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
582
583 // we dont want events no more
584 XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
585
586 frame->hide();
587
588 // give the client its border back
589 client->toggleClientBorder(true);
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 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 // force the callbacks to fire
664 if (!Openbox::instance->focusedClient())
665 Openbox::instance->setFocusedClient(0);
666 }
667
668 void OBScreen::changeNumDesktops(long num)
669 {
670 assert(num > 0);
671
672 if (!(num > 0)) return;
673
674 // XXX: move windows on desktops that will no longer exist!
675
676 _num_desktops = num;
677 Openbox::instance->property()->set(_info->rootWindow(),
678 otk::OBProperty::net_number_of_desktops,
679 otk::OBProperty::Atom_Cardinal,
680 _num_desktops);
681
682 // set the viewport hint
683 unsigned long *viewport = new unsigned long[_num_desktops * 2];
684 memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
685 Openbox::instance->property()->set(_info->rootWindow(),
686 otk::OBProperty::net_desktop_viewport,
687 otk::OBProperty::Atom_Cardinal,
688 viewport, _num_desktops * 2);
689 delete [] viewport;
690
691 // update the work area hint
692 changeWorkArea();
693 }
694
695
696 void OBScreen::updateDesktopNames()
697 {
698 const otk::OBProperty *property = Openbox::instance->property();
699
700 unsigned long num = (unsigned) -1;
701
702 if (!property->get(_info->rootWindow(),
703 otk::OBProperty::net_desktop_names,
704 otk::OBProperty::utf8, &num, &_desktop_names))
705 _desktop_names.clear();
706 while ((long)_desktop_names.size() < _num_desktops)
707 _desktop_names.push_back("Unnamed");
708 }
709
710
711 void OBScreen::setDesktopName(long i, const std::string &name)
712 {
713 assert(i >= 0);
714
715 if (i >= _num_desktops) return;
716
717 const otk::OBProperty *property = Openbox::instance->property();
718
719 otk::OBProperty::StringVect newnames = _desktop_names;
720 newnames[i] = name;
721 property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names,
722 otk::OBProperty::utf8, newnames);
723 }
724
725
726 void OBScreen::propertyHandler(const XPropertyEvent &e)
727 {
728 otk::OtkEventHandler::propertyHandler(e);
729
730 const otk::OBProperty *property = Openbox::instance->property();
731
732 // compress changes to a single property into a single change
733 XEvent ce;
734 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
735 // XXX: it would be nice to compress ALL changes to a property, not just
736 // changes in a row without other props between.
737 if (ce.xproperty.atom != e.atom) {
738 XPutBackEvent(otk::OBDisplay::display, &ce);
739 break;
740 }
741 }
742
743 if (e.atom == property->atom(otk::OBProperty::net_desktop_names))
744 updateDesktopNames();
745 }
746
747
748 void OBScreen::clientMessageHandler(const XClientMessageEvent &e)
749 {
750 otk::OtkEventHandler::clientMessageHandler(e);
751
752 if (e.format != 32) return;
753
754 const otk::OBProperty *property = Openbox::instance->property();
755
756 if (e.message_type == property->atom(otk::OBProperty::net_current_desktop)) {
757 changeDesktop(e.data.l[0]);
758 } else if (e.message_type ==
759 property->atom(otk::OBProperty::net_number_of_desktops)) {
760 changeNumDesktops(e.data.l[0]);
761 }
762 // XXX: so many client messages to handle here! ..or not.. they go to clients
763 }
764
765
766 void OBScreen::mapRequestHandler(const XMapRequestEvent &e)
767 {
768 otk::OtkEventHandler::mapRequestHandler(e);
769
770 #ifdef DEBUG
771 printf("MapRequest for 0x%lx\n", e.window);
772 #endif // DEBUG
773
774 /*
775 MapRequest events come here even after the window exists instead of going
776 right to the client window, because of how they are sent and their struct
777 layout.
778 */
779 OBClient *c = Openbox::instance->findClient(e.window);
780
781 if (c) {
782 if (c->shaded())
783 c->shade(false);
784 // XXX: uniconify the window
785 c->focus();
786 } else
787 manageWindow(e.window);
788 }
789 }
This page took 0.072082 seconds and 5 git commands to generate.