bringing window list menu in, slowly
[bbkeys.git] / src / ScreenHandler.cpp
blobb3b9495114bd9e1e13967d82f6c0d9f5a046df13
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // -- ScreenHandler.cpp --
3 // Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // E_O_H_VR
25 #include "../config.h"
27 extern "C" {
28 #ifdef HAVE_STDIO_H
29 # include <stdio.h>
30 #endif // HAVE_STDIO_H
32 #ifdef HAVE_UNISTD_H
33 # include <sys/types.h>
34 # include <unistd.h>
35 #endif // HAVE_UNISTD_H
37 #include <X11/keysym.h>
40 #include "ScreenHandler.h"
42 using std::cout;
44 //--------------------------------------------------------
45 // Constructor/Destructor
46 //--------------------------------------------------------
47 ScreenHandler::ScreenHandler (KeyClient * k, unsigned int number)
48 : _managed(true), _screenNumber(number),
49 _screenInfo(k->display().screenInfo(number)),
50 _clients(k->clientsList()), _active(k->activeWindow())
52 _keyClient = k;
53 _netclient = k->getNetclient();
54 _config = k->getConfig();
55 _display = k->XDisplay();
56 _last_active = _clients.end();
57 _keyGrabber = k->getKeyGrabber();
58 _keybindings = k->getKeybindings();
59 _root = _screenInfo.rootWindow();
61 // get our lockmasks from bt::Application
62 k->getLockModifiers(_numlockMask, _scrolllockMask);
64 // find a window manager supporting NETWM, waiting for it to load if we must
65 int count = 20; // try 20 times
66 _managed = false;
67 while (! (_keyClient->shuttingDown() || _managed || count <= 0)) {
68 if (! (_managed = findSupportingWM()))
69 sleep(5);
70 --count;
73 if (!_managed) {
74 cout << "ScreenHandler: Unable to find a "
75 << "compatible window manager for screen: [" << number << "].\n";
76 return;
79 bt::Netwm::AtomList atoms;
80 if (_netclient->readSupported(_root, atoms)) {
81 cout << "ScreenHandler: Supported atoms: [" << atoms.size() << "].\n";
82 } else {
83 cout << "ScreenHandler: No supported ewmh hints. Not able to be managed.\n";
84 _managed = false;
85 return;
88 XSelectInput(_display, _root,
89 PropertyChangeMask | KeyPressMask | KeyReleaseMask);
91 // add an event handler for our root window
92 k->insertEventHandler(_root, this);
94 // get configuration options
95 _honor_modifiers = _config->getBoolValue("honormodifiers", false);
96 _raise_while_cycling = _config->getBoolValue("raisewhilecycling", true);
97 _show_cycle_menu = _config->getBoolValue("showcyclemenu", true);
98 _menu_text_justify = _config->getStringValue("menutextjustify", "left");
99 _workspace_columns = _config->getNumberValue("workspacecolumns", 0);
100 _workspace_rows = _config->getNumberValue("workspacerows", 0);
101 _debug = _config->getBoolValue("debug", false);
103 _cycling = false;
105 // our popup window list menu
106 _windowmenu = new WindowlistMenu(this);
109 ScreenHandler::~ScreenHandler ()
111 _keyClient->removeEventHandler( _root );
113 _keyGrabber->ungrabAll(_root);
115 if (_managed)
116 XSelectInput(_display, _root, None);
119 void ScreenHandler::initialize()
121 _keybindings->grabDefaults(this);
123 updateActiveDesktop();
124 updateNumDesktops();
125 updateClientList();
126 updateActiveWindow();
128 // load graphics resource from config file
129 bt::Resource res(_config->getStringValue("stylefile", "/tmp/needstyle"));
130 bt::MenuStyle::get(_keyClient->getMainApplication(),
131 _screenNumber)->load(res);
136 bool ScreenHandler::findSupportingWM() {
138 if (_debug)
139 cout << endl << "ScreenHandler: in findSupportingWM."<< endl;
141 Window client, tmp;
142 bool res = false;
144 res = _netclient->readSupportingWMCheck(_root, &client);
145 if (!res) {
146 if (_debug)
147 cout << "ScreenHandler: first readSupportingWMCheck failed." << endl;
148 return false;
151 if (_debug)
152 cout << "ScreenHandler: first readSupportingWMCheck succeeded." << endl;
154 res = _netclient->readSupportingWMCheck(client, &tmp);
155 if (!res || client != tmp) {
156 if (_debug)
157 cout << "ScreenHandler: second readSupportingWMCheck failed." << endl;
158 return false;
161 if (_debug)
162 cout << "ScreenHandler: second readSupportingWMCheck worked." << endl;
164 // now try to get the name of the window manager, using utf8 first
165 // and falling back to ansi if that fails
168 // try netwm
169 if (! _netclient->getValue(client, _netclient->wmName(),
170 Netclient::utf8, _wm_name)) {
171 if (_debug)
172 cout << "ScreenHandler: first try at getting wmName failed." << endl;
173 // try old x stuff
174 _netclient->getValue(client, XA_WM_NAME, Netclient::ansi, _wm_name);
177 if (_wm_name.empty()) {
178 if (_debug)
179 cout << "ScreenHandler: couldn't get wm's name. letting it slide this time...." << endl;
180 _wm_name = "beats the heck out of me";
183 cout << "ScreenHandler: Found compatible "
184 << "window manager: [" << _wm_name << "] for screen: ["
185 << _screenNumber << "].\n";
187 return true;
191 void ScreenHandler::grabKey(const KeyCode keyCode,
192 const int modifierMask) const {
193 _keyGrabber->grab(keyCode, modifierMask, _root );
196 void ScreenHandler::ungrabKey(const KeyCode keyCode,
197 const int modifierMask) const {
198 _keyGrabber->ungrab(keyCode, modifierMask, _root );
201 void ScreenHandler::keyPressEvent (const XKeyEvent * const e)
203 unsigned int state = e->state;
205 // Mask out the lock modifiers unless our user doesn't want this
206 if (! _honor_modifiers) {
207 state= e->state & ~(LockMask|_scrolllockMask|_numlockMask);
210 // first, check to see if we're in the middle of a window cycling
211 // loop-de-loop and we're getting a cancel....
212 if (_cycling && e->keycode == XKeysymToKeycode(_display, XK_Escape)) {
214 // we've been told to cancel out of a cycleWindow loop, so we turn
215 // off cycling, ungrab the keyboard, then raise the last-active
216 // window for our user
217 _cycling = false;
218 XUngrabKeyboard(_display, CurrentTime);
220 const XWindow * la = lastActiveWindow();
222 if (la) la->focus(true);
224 return;
227 // if we've made it this far, handle the action....
228 const Action *it = _keybindings->getAction(e, state, this);
230 if (!it)
231 return;
233 switch (it->type()) {
235 case Action::chain:
236 // if we're doing a chain, then keytree has done everything for us...
237 // just return
238 return;
240 case Action::nextScreen:
241 _keyClient->cycleScreen(_screenNumber, true);
242 return;
244 case Action::prevScreen:
245 _keyClient->cycleScreen(_screenNumber, false);
246 return;
248 case Action::nextWorkspace:
249 cycleWorkspace(true, it->number() != 0 ? it->number(): 1);
250 return;
252 case Action::prevWorkspace:
253 cycleWorkspace(false, it->number() != 0 ? it->number(): 1);
254 return;
256 case Action::nextWindow:
257 cycleWindow(state, true, it->number() != 0 ? it->number(): 1);
258 return;
260 case Action::prevWindow:
261 cycleWindow(state, false, it->number() != 0 ? it->number(): 1);
262 return;
264 case Action::nextWindowOnAllWorkspaces:
265 cycleWindow(state, true, it->number() != 0 ? it->number(): 1, false, true);
266 return;
268 case Action::prevWindowOnAllWorkspaces:
269 cycleWindow(state, false, it->number() != 0 ? it->number(): 1, false, true);
270 return;
272 case Action::nextWindowOnAllScreens:
273 cycleWindow(state, true, it->number() != 0 ? it->number(): 1, true);
274 return;
276 case Action::prevWindowOnAllScreens:
277 cycleWindow(state, false, it->number() != 0 ? it->number(): 1, true);
278 return;
280 case Action::nextWindowOfClass:
281 cycleWindow(state, true, it->number() != 0 ? it->number(): 1,
282 false, false, true, it->string());
283 return;
285 case Action::prevWindowOfClass:
286 cycleWindow(state, false, it->number() != 0 ? it->number(): 1,
287 false, false, true, it->string());
288 return;
290 case Action::nextWindowOfClassOnAllWorkspaces:
291 cycleWindow(state, true, it->number() != 0 ? it->number(): 1,
292 false, true, true, it->string());
293 return;
295 case Action::prevWindowOfClassOnAllWorkspaces:
296 cycleWindow(state, false, it->number() != 0 ? it->number(): 1,
297 false, true, true, it->string());
298 return;
300 case Action::changeWorkspace:
301 changeWorkspace(it->number());
302 return;
304 case Action::upWorkspace:
305 changeWorkspaceVert(-1);
306 return;
308 case Action::downWorkspace:
309 changeWorkspaceVert(1);
310 return;
312 case Action::leftWorkspace:
313 changeWorkspaceHorz(-1);
314 return;
316 case Action::rightWorkspace:
317 changeWorkspaceHorz(1);
318 return;
320 case Action::execute:
321 execCommand(it->string());
322 return;
324 case Action::showRootMenu:
325 _netclient->sendClientMessage(_root, _netclient->xaOpenboxShowRootMenu(),
326 None);
327 return;
329 case Action::showWorkspaceMenu:
330 _netclient->sendClientMessage(_root, _netclient->xaOpenboxShowWorkspaceMenu(),
331 None);
332 return;
334 case Action::toggleGrabs: {
335 if (_grabbed) {
336 _keybindings->ungrabDefaults(this);
337 _grabbed = false;
338 } else {
339 _keybindings->grabDefaults(this);
340 _grabbed = true;
342 return;
345 default:
346 break;
349 // these actions require an active window
350 if (_active != _clients.end()) {
351 XWindow *window = *_active;
353 switch (it->type()) {
354 case Action::iconify:
355 window->iconify();
356 return;
358 case Action::close:
359 window->close();
360 return;
362 case Action::raise:
363 window->raise();
364 return;
366 case Action::lower:
367 window->lower();
368 return;
370 case Action::sendToWorkspace:
371 window->sendTo(it->number());
372 return;
374 case Action::toggleOmnipresent:
375 if (window->desktop() == 0xffffffff)
376 window->sendTo(_active_desktop);
377 else
378 window->sendTo(0xffffffff);
379 return;
381 case Action::moveWindowUp:
382 window->move(0, -(it->number() != 0 ? it->number(): 1));
383 return;
385 case Action::moveWindowDown:
386 window->move(0, it->number() != 0 ? it->number(): 1);
387 return;
389 case Action::moveWindowLeft:
390 window->move(-(it->number() != 0 ? it->number(): 1), 0);
391 return;
393 case Action::moveWindowRight:
394 window->move(it->number() != 0 ? it->number(): 1,0);
395 return;
397 case Action::resizeWindowWidth:
398 window->resizeRel(it->number(), 0);
399 return;
401 case Action::resizeWindowHeight:
402 window->resizeRel(0, it->number());
403 return;
405 case Action::toggleShade:
406 window->shade(! window->shaded());
407 return;
409 case Action::toggleMaximizeHorizontal:
410 window->toggleMaximize(XWindow::Max_Horz);
411 return;
413 case Action::toggleMaximizeVertical:
414 window->toggleMaximize(XWindow::Max_Vert);
415 return;
417 case Action::toggleMaximizeFull:
418 window->toggleMaximize(XWindow::Max_Full);
419 return;
421 case Action::toggleDecorations:
422 window->decorate(! window->decorated());
423 return;
425 default:
426 assert(false); // unhandled action type!
427 break;
432 void ScreenHandler::keyReleaseEvent (const XKeyEvent * const e)
434 // the only keyrelease event we care about (for now) is when we do window
435 // cycling and the modifier is released
436 if ( _cycling && nothingIsPressed()) {
437 // all modifiers have been released. ungrab the keyboard, move the
438 // focused window to the top of the Z-order and raise it
439 XUngrabKeyboard(_display, CurrentTime);
441 if (_active != _clients.end()) {
442 XWindow *w = *_active;
443 bool e = _last_active == _active;
444 _clients.remove(w);
445 _clients.push_front(w);
446 _active = _clients.begin();
447 if (!e) _last_active = _active;
448 w->raise();
451 _cycling = false;
455 void ScreenHandler::propertyNotifyEvent(const XPropertyEvent * const e)
457 if (e->atom == _netclient->numberOfDesktops()) {
458 updateNumDesktops();
459 } else if (e->atom == _netclient->currentDesktop()) {
460 updateActiveDesktop();
461 } else if (e->atom == _netclient->activeWindow()) {
462 updateActiveWindow();
463 } else if (e->atom == _netclient->clientList()) {
464 updateClientList();
468 void ScreenHandler::updateNumDesktops()
470 assert(_managed);
472 if (! _netclient->readNumberOfDesktops(_root, & _num_desktops))
473 _num_desktops = 1; // assume that there is at least 1 desktop!
477 void ScreenHandler::updateActiveDesktop()
479 assert(_managed);
481 if (! _netclient->readCurrentDesktop(_root, & _active_desktop))
482 _active_desktop = 0; // there must be at least one desktop, and it must
483 // be the current one
487 void ScreenHandler::updateActiveWindow()
489 assert(_managed);
491 Window a = None;
492 _netclient->getValue(_root, _netclient->activeWindow(), XA_WINDOW, a);
494 if ( None == a ) {
495 return;
498 WindowList::iterator it, end = _clients.end();
499 for (it = _clients.begin(); it != end; ++it) {
500 if ( (*it)->window() == a) {
501 if ( (*it)->getScreenNumber() != _screenNumber )
502 return;
503 break;
507 _active = it;
509 if (_active != end) {
510 /* if we're not cycling and a window gets focus, add it to the top of the
511 * cycle stack.
514 if ( !_cycling) {
515 XWindow *win = *_active;
516 _clients.remove(win);
517 _clients.push_front(win);
518 _active = _clients.begin();
520 _last_active = _active;
522 if ( _debug )
523 cout <<"active window now: [" <<(*_active)->title() <<"]" <<endl;
530 void ScreenHandler::updateClientList()
533 assert(_managed);
535 WindowList::iterator insert_point = _active;
536 if (insert_point != _clients.end())
537 ++insert_point; // get to the item client the focused client
539 // get the client list from the root window
540 Netclient::WindowList rootclients;
541 unsigned long num = (unsigned) -1;
543 if ( ! _netclient->readClientList(_root, rootclients) ) {
544 cerr << "couldn't get client list from WM.\n";
545 num = 0;
546 } else {
547 num = rootclients.size();
550 WindowList::iterator it;
551 const WindowList::iterator end = _clients.end();
552 unsigned long i;
554 for (i = 0; i < num; ++i) {
555 for (it = _clients.begin(); it != end; ++it)
556 if (**it == rootclients[i])
557 break;
558 if (it == end) { // didn't already exist
559 if (careAboutWindow(rootclients[i])) {
560 XWindow * wTmp = new XWindow( rootclients[i], _netclient, _screenInfo , *_keyClient );
561 _clients.insert(insert_point, wTmp);
566 // remove clients that no longer exist (that belong to this screen)
567 for (it = _clients.begin(); it != end;) {
568 WindowList::iterator it2 = it;
569 ++it;
571 // is on another screen?
572 if ((*it2)->getScreenNumber() != _screenNumber)
573 continue;
575 for (i = 0; i < num; ++i)
576 if (**it2 == rootclients[i])
577 break;
578 if (i == num) { // no longer exists
579 // watch for the active and last-active window
580 if (it2 == _active)
581 _active = _clients.end();
582 if (it2 == _last_active)
583 _last_active = _clients.end();
584 delete *it2;
585 _clients.erase(it2);
592 // do we care about this window as a client?
593 bool ScreenHandler::careAboutWindow(Window window) const
595 assert(_managed);
597 Atom type;
598 if (! _netclient->getValue(window, _netclient->wmWindowType(), XA_ATOM,
599 type)) {
600 return True;
603 if (type == _netclient->wmWindowTypeDock() ||
604 type == _netclient->wmWindowTypeMenu() ) {
605 return False;
606 } else {
607 return True;
611 XWindow * ScreenHandler::findWindow(Window window) const {
612 assert(_managed);
614 WindowList::const_iterator it, end = _clients.end();
615 for (it = _clients.begin(); it != end; ++it)
616 if (**it == window)
617 break;
618 if(it == end)
619 return 0;
620 return *it;
623 void ScreenHandler::execCommand(const string &cmd) const {
624 pid_t pid;
625 if ((pid = fork()) == 0) {
626 // disconnect the child from this session and the tty
627 if (setsid() == -1) {
628 cout << "warning: could not start a new process group\n";
629 perror("setsid");
632 // make the command run on the correct screen
633 if (putenv(const_cast<char*>(_screenInfo.displayString().c_str()))) {
634 cout << "warning: couldn't set environment variable 'DISPLAY'\n";
635 perror("putenv()");
637 execl("/bin/sh", "sh", "-c", cmd.c_str(), NULL);
638 exit(-1);
639 } else if (pid == -1) {
640 cout << ": Could not fork a process for executing a command\n";
644 WindowList ScreenHandler::getCycleWindowList(unsigned int state, const bool forward,
645 const int increment, const bool allscreens,
646 const bool alldesktops, const bool sameclass,
647 const string &cn)
649 assert(_managed);
650 assert(increment > 0);
652 WindowList theList;
654 if (_clients.empty()) return theList;
656 string classname(cn);
657 if (sameclass && classname.empty() && _active != _clients.end())
658 classname = (*_active)->appClass();
661 WindowList::const_iterator it = _active;
662 const WindowList::const_iterator end = _clients.end();
664 for (; it != end; ++it) {
665 XWindow *t = 0;
667 // determine if this window is invalid for cycling to
668 t = *it;
669 if (t->iconic()) continue;
670 if (! allscreens && t->getScreenNumber() != _screenNumber) continue;
671 if (! alldesktops && ! (t->desktop() == _active_desktop ||
672 t->desktop() == 0xffffffff)) continue;
673 if (sameclass && ! classname.empty() &&
674 t->appClass() != classname) continue;
675 if (! t->canFocus()) continue;
677 // found a focusable window
678 theList.push_back(t);
681 return theList;
685 void ScreenHandler::cycleWindow(unsigned int state, const bool forward,
686 const int increment, const bool allscreens,
687 const bool alldesktops, const bool sameclass,
688 const string &cn)
690 assert(_managed);
691 assert(increment > 0);
693 if (_clients.empty()) return;
695 // if our user wants the window cycling menu to show (who wouldn't!!
696 // =:) ) and if it's not already showing...
697 if ( _show_cycle_menu && ! _windowmenu->isVisible() ) {
698 if (_debug)
699 std::cout << "ScreenHandler: menu not visible. loading and showing..." << std::endl;
701 _cycling = true;
702 WindowList theList = getCycleWindowList(state, forward, increment,
703 allscreens, alldesktops,
704 sameclass, cn);
705 _windowmenu->showCycleMenu(theList);
706 return;
710 string classname(cn);
711 if (sameclass && classname.empty() && _active != _clients.end())
712 classname = (*_active)->appClass();
714 WindowList::const_iterator target = _active,
715 begin = _clients.begin(),
716 end = _clients.end();
718 XWindow *t = 0;
720 for (int x = 0; x < increment; ++x) {
721 while (1) {
722 if (forward) {
723 if (target == end)
724 target = begin;
725 else
726 ++target;
727 } else {
728 if (target == begin)
729 target = end;
730 else
731 --target;
734 // must be no window to focus
735 if (target == _active)
736 return;
738 // start back at the beginning of the loop
739 if (target == end)
740 continue;
742 // determine if this window is invalid for cycling to
743 t = *target;
744 if (t->iconic()) continue;
745 if (! allscreens && t->getScreenNumber() != _screenNumber) continue;
746 if (! alldesktops && ! (t->desktop() == _active_desktop ||
747 t->desktop() == 0xffffffff)) continue;
748 if (sameclass && ! classname.empty() &&
749 t->appClass() != classname) continue;
750 if (! t->canFocus()) continue;
752 // found a good window so break out of the while, and perhaps continue
753 // with the for loop
754 break;
758 // phew. we found the window, so focus it.
759 if ( state) {
760 if (!_cycling) {
761 // grab keyboard so we can intercept KeyReleases from it
762 XGrabKeyboard(_display, _root, True, GrabModeAsync,
763 GrabModeAsync, CurrentTime);
764 _cycling = true;
767 // if the window is on another desktop, we can't use XSetInputFocus, since
768 // it doesn't imply a workspace change.
769 if ( t->desktop() != _active_desktop &&
770 t->desktop() != 0xffffffff)
771 t->focus(); // raise
772 else
773 t->focus(false); // don't raise
775 else {
776 t->focus();
781 void ScreenHandler::cycleWorkspace(const bool forward, const int increment,
782 const bool loop) const {
783 assert(_managed);
784 assert(increment > 0);
786 unsigned int destination = _active_desktop;
788 for (int x = 0; x < increment; ++x) {
789 if (forward) {
790 if (destination < _num_desktops - 1)
791 ++destination;
792 else if (loop)
793 destination = 0;
794 } else {
795 if (destination > 0)
796 --destination;
797 else if (loop)
798 destination = _num_desktops - 1;
802 if (destination != _active_desktop)
803 changeWorkspace(destination);
807 void ScreenHandler::changeWorkspace(const int num) const {
808 assert(_managed);
810 _netclient->sendClientMessage(_root, _netclient->currentDesktop(), _root, num);
813 void ScreenHandler::changeWorkspaceVert(const int num) const {
814 assert(_managed);
815 int width = _workspace_columns;
816 int num_desktops = (signed)_num_desktops;
817 int active_desktop = (signed)_active_desktop;
818 int wnum = 0;
820 if (width > num_desktops || width <= 0)
821 return;
823 // a cookie to the person that makes this pretty
824 if (num < 0) {
825 wnum = active_desktop - width;
826 if (wnum < 0) {
827 wnum = num_desktops/width * width + active_desktop;
828 if (wnum >= num_desktops)
829 wnum = num_desktops - 1;
832 else {
833 wnum = active_desktop + width;
834 if (wnum >= num_desktops) {
835 wnum = (active_desktop + width) % num_desktops - 1;
836 if (wnum < 0)
837 wnum = 0;
840 changeWorkspace(wnum);
843 void ScreenHandler::changeWorkspaceHorz(const int num) const {
844 assert(_managed);
845 int width = _workspace_columns;
846 int num_desktops = (signed)_num_desktops;
847 int active_desktop = (signed)_active_desktop;
848 int wnum = 0;
850 if (width > num_desktops || width <= 0)
851 return;
853 if (num < 0) {
854 if (active_desktop % width != 0)
855 wnum = active_desktop - 1;
856 else {
857 wnum = active_desktop + width - 1;
858 if (wnum >= num_desktops)
859 wnum = num_desktops - 1;
862 else {
863 if (active_desktop % width != width - 1) {
864 wnum = active_desktop + 1;
865 if (wnum >= num_desktops)
866 wnum = num_desktops / width * width;
868 else
869 wnum = active_desktop - width + 1;
871 changeWorkspace(wnum);
874 bool ScreenHandler::nothingIsPressed(void) const
876 char keys[32];
877 XQueryKeymap(_display, keys);
879 for (int i = 0; i < 32; ++i) {
880 if (keys[i] != 0)
881 return false;
884 return true;
887 const XWindow *ScreenHandler::lastActiveWindow() const {
888 if (_last_active != _clients.end())
889 return *_last_active;
891 // find a window if one exists
892 WindowList::const_iterator it, end = _clients.end();
893 for (it = _clients.begin(); it != end; ++it)
894 if ((*it)->getScreenNumber() == _screenNumber && ! (*it)->iconic() &&
895 (*it)->canFocus() &&
896 ((*it)->desktop() == 0xffffffff ||
897 (*it)->desktop() == _active_desktop))
898 return *it;
900 // no windows on this screen
901 return 0;
904 void ScreenHandler::p()
906 cout << "\nNOW LISTING CLIENTS!!!" << endl;
908 WindowList::const_iterator it = _clients.begin();
909 const WindowList::const_iterator end = _clients.end();
911 for (; it != end; ++it)
912 cout << "desktop: ["
913 << (*it)->desktop()
914 << "], window: [" << (*it)->title() << "]" << endl;