/*
* 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 <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#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<Blwm>::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<Blwm>::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<Blwm>::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<Blwm>::Iterator i(&mapList);
for (Blwm* tmpBlwm = i.GetHead(); tmpBlwm; tmpBlwm = i.GetNext())
if (tmpBlwm == blWm)
return False;
return True;
}
syntax highlighted by Code2HTML, v. 0.9.1