/* * focus_mgr.cc * * Copyright (C) 1995, 1996, 1997, 1997, 1998, 1999, 2000, 2001, 2002 Kenichi Kourai * Copyright (C) 1999, 2000, 2001, 2002 Luiz Blanes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with blwm; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "main.h" #include "util.h" #include "blwm.h" #include "focus_mgr.h" #include "blwmrc.h" #include "key.h" #include "pager.h" #include "mini.h" #include "paging.h" #include "fbutton.h" #include "desktop.h" void FocusMgr::SetFocus(Blwm* blWm) { ASSERT(blWm); Blwm::focusBlwm = blWm; if (blWm == rootBlwm) { desktop.SetFocus(); scKey->GrabKeys(root); blWm->InstallWindowColormaps(); // DumpStack(); return; } if (blWm->CheckMapped()) { /* * Ungrab buttons so that the window without focus can get focus by * ButtonPress. */ if (AutoRaise && blWm == Blwm::activeBlwm) for (int i = 1; i < 4; i++) XUngrabButton(display, i, 0, blWm->GetWin()); /* * Set the input focus to this window. */ XSetInputFocus(display, blWm->GetWin(), RevertToParent, CurrentTime); blWm->InstallWindowColormaps(); /* * Redraw according to focus change */ blWm->DrawTitle(True); blWm->ChangeFrameFocus(); for (int i = 0; i < 3; i++) blWm->fButton[i]->DrawButton(); } ASSERT(blWm->tButton); blWm->tButton->SetFocus(); blWm->tButton->SetState(Button::PUSH); blWm->tButton->DrawButton(); if (UsePager) { ASSERT(blWm->mini); blWm->mini->SetFocus(); } // move blWm to the top of the focus stack // XXX even if a transient window, give it a focus in the above if (!blWm->CheckFlags(TRANSIENT)) { Remove(blWm); Push(blWm); } if (blWm->CheckFlags(WM_TAKE_FOCUS)) blWm->SendMessage(_XA_WM_TAKE_FOCUS); // DumpStack(); } void FocusMgr::ResetFocus(Blwm* blWm) { ASSERT(blWm); Blwm::focusBlwm = NULL; if (blWm == rootBlwm) { scKey->UngrabKeys(root); return; } if (blWm->CheckMapped()) { /* * Grab buttons so that the window without focus can get focus by * ButtonPress. */ for (int i = 1; i < 4; i++) XGrabButton(display, i, 0, blWm->GetWin(), True, ButtonPressMask, GrabModeSync, GrabModeAsync, None, cursor[SYS]); } /* * Redraw according to focus change */ blWm->DrawTitle(True); blWm->ChangeFrameFocus(); for (int i = 0; i < 3; i++) blWm->fButton[i]->DrawButton(); ASSERT(blWm->tButton); blWm->tButton->ResetFocus(); blWm->tButton->SetState(Button::NORMAL); blWm->tButton->DrawButton(); if (UsePager) { ASSERT(blWm->mini); blWm->mini->ResetFocus(); } } /* * RollFocus -- * Roll focus stack: that is, the top becomes the bottom, and the second * is the top. */ void FocusMgr::RollFocus(Bool forward) { Blwm* blWm; if (forward) { // move this window to the last of the focus list blWm = focusMgr.Pop(); focusMgr.InsertBottom(blWm); blWm = focusMgr.Top(); } else { // move the last of the focus list to the top of the stack blWm = focusMgr.RemoveBottom(); focusMgr.Push(blWm); } ASSERT(blWm->CheckMapped()); blWm->SetFocus(); blWm->RaiseWindow(True); blWm->AdjustPage(); } /* * Roll focus stack within the same screen, not including windows with * NOFOCUS or STICKY. */ void FocusMgr::RollFocusWithinScreen(Bool forward) { Blwm* blWm; List::Iterator i(&focusMgr.GetMapList()); Rect vt(paging->origin.x, paging->origin.y, rcScreen.width, rcScreen.height); if (forward) { // move the top window to the bottom if it has a focus if (Blwm::focusBlwm != rootBlwm && !Blwm::focusBlwm->CheckFlags(STICKY) && Intersect(Blwm::focusBlwm->GetRect(), vt)) { blWm = focusMgr.Pop(); focusMgr.InsertBottom(blWm); } // search the next window within the same screen for (blWm = i.GetHead(); blWm; blWm = i.GetNext()) { if (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)) { i.Remove(); focusMgr.Push(blWm); break; } } } else { // search the next window within the same screen for (blWm = i.GetTail(); blWm; blWm = i.GetPrev()) { if (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)) { i.Remove(); focusMgr.Push(blWm); break; } } } if (blWm == NULL) blWm = rootBlwm; ASSERT(blWm->CheckMapped()); blWm->SetFocus(); blWm->RaiseWindow(True); } ////////////////////////////////////////////////////////////////////// // debug function void FocusMgr::DumpStack() { List::Iterator i(&mapList); printf("FOCUS: %s\n", Blwm::focusBlwm->GetName()); printf("MAP LIST: "); for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) printf("%s -> ", blWm->GetName()); printf("\n"); i = List::Iterator(&unmapList); printf("UNMAP LIST: "); for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) printf("%s -> ", blWm->GetName()); printf("\n"); printf("\n"); } Bool FocusMgr::Check(Blwm* blWm) { List::Iterator i(&mapList); for (Blwm* tmpBlwm = i.GetHead(); tmpBlwm; tmpBlwm = i.GetNext()) if (tmpBlwm == blWm) return False; return True; }