fix some flickering on focus change

This commit is contained in:
Mark Tiefenbruck 2008-01-01 10:29:36 -08:00
parent 72d2f0e481
commit 7588fc10a6
5 changed files with 63 additions and 80 deletions

View file

@ -251,10 +251,9 @@ Focusable *FocusControl::lastFocusedWindow(int workspace) {
Focusables::iterator it = m_focused_list.clientList().begin();
Focusables::iterator it_end = m_focused_list.clientList().end();
for (; it != it_end; ++it) {
if ((*it)->fbwindow() &&
if ((*it)->fbwindow() && (*it)->acceptsFocus() &&
((((int)(*it)->fbwindow()->workspaceNumber()) == workspace ||
(*it)->fbwindow()->isStuck()) && (*it)->acceptsFocus() &&
!(*it)->fbwindow()->isIconic()))
(*it)->fbwindow()->isStuck()) && !(*it)->fbwindow()->isIconic()))
return *it;
}
return 0;
@ -531,7 +530,8 @@ void FocusControl::setFocusedWindow(WinClient *client) {
#endif // DEBUG
// Update the old focused client to non focus
if (s_focused_fbwindow)
if (s_focused_fbwindow &&
(!client || client->fbwindow() != s_focused_fbwindow))
s_focused_fbwindow->setFocusFlag(false);
if (client && client->fbwindow() && !client->fbwindow()->isIconic()) {

View file

@ -140,6 +140,7 @@ WinClient::~WinClient() {
transients.pop_back();
}
accepts_input = send_focus_message = false;
if (fbwindow() != 0)
fbwindow()->removeClient(*this);

View file

@ -1013,10 +1013,21 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
WinClient *old = m_client;
m_client = &client;
bool ret = setinput && focus();
if (setinput) {
m_client = old;
return ret;
}
m_client->raise();
if (setinput != m_focused || setinput && m_client != old)
if (m_focused) {
m_client->focusSig().notify();
titleSig().notify();
if (old)
old->focusSig().notify();
}
if (old != &client)
titleSig().notify();
#ifdef DEBUG
cerr<<"FluxboxWindow::"<<__FUNCTION__<<": labelbutton[client] = "<<
@ -1025,16 +1036,6 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
// frame focused doesn't necessarily mean input focused
frame().setLabelButtonFocus(*button);
frame().setShapingClient(&client, false);
bool ret = setinput && focus();
if (setinput) {
// restore old client until focus event comes
m_client = old;
if (!ret && old) {
old->raise();
titleSig().notify();
}
}
return ret;
}

View file

@ -218,7 +218,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
m_masked(0),
m_rc_file(rcfilename ? rcfilename : ""),
m_argv(argv), m_argc(argc),
m_revert_screen(0),
m_showing_dialog(false),
m_starting(true),
m_restarting(false),
@ -274,12 +273,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
m_reconfig_timer.setCommand(reconfig_cmd);
m_reconfig_timer.fireOnce(true);
// set a timer to revert focus on FocusOut, in case no FocusIn arrives
FbTk::RefCount<FbTk::Command> revert_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::revert_focus));
m_revert_timer.setCommand(revert_cmd);
m_revert_timer.setTimeout(to);
m_revert_timer.fireOnce(true);
// XSynchronize(disp, True);
s_singleton = this;
@ -546,7 +539,7 @@ void Fluxbox::eventLoop() {
if (last_bad_window != None && e.xany.window == last_bad_window &&
e.type != DestroyNotify) { // we must let the actual destroys through
if (e.type == FocusOut)
m_revert_timer.start();
revertFocus();
#ifdef DEBUG
else
cerr<<"Fluxbox::eventLoop(): removing bad window from event queue"<<endl;
@ -711,30 +704,6 @@ void Fluxbox::handleEvent(XEvent * const e) {
}
}
// we need to check focus out for menus before
// we call FbTk eventhandler
// so we can get FbTk::Menu::focused() before it sets to 0
if (e->type == FocusOut &&
e->xfocus.mode != NotifyGrab &&
e->xfocus.detail != NotifyPointer &&
e->xfocus.detail != NotifyInferior &&
FbTk::Menu::focused() != 0 &&
FbTk::Menu::focused()->window() == e->xfocus.window) {
// find screen num
ScreenList::iterator it = m_screen_list.begin();
ScreenList::iterator it_end = m_screen_list.end();
for (; it != it_end; ++it) {
if ( (*it)->screenNumber() ==
FbTk::Menu::focused()->fbwindow().screenNumber()) {
FocusControl::setFocusedWindow(0);
m_revert_screen = *it;
m_revert_timer.start();
break; // found the screen, no more search
}
}
}
// try FbTk::EventHandler first
FbTk::EventManager::instance()->handleEvent(*e);
@ -903,9 +872,18 @@ void Fluxbox::handleEvent(XEvent * const e) {
e->xfocus.detail == NotifyPointer ||
e->xfocus.detail == NotifyInferior)
break;
if (FbTk::Menu::focused() &&
FbTk::Menu::focused()->window() == e->xfocus.window) {
m_keyscreen = findScreen(FbTk::Menu::focused()->screenNumber());
break;
}
WinClient *winclient = searchWindow(e->xfocus.window);
if (winclient && FocusControl::focusedWindow() != winclient)
FocusControl::setFocusedWindow(winclient);
if (!winclient)
break;
m_keyscreen = &winclient->screen();
FocusControl::setFocusedWindow(winclient);
} break;
case FocusOut:{
@ -916,19 +894,11 @@ void Fluxbox::handleEvent(XEvent * const e) {
break;
WinClient *winclient = searchWindow(e->xfocus.window);
if (winclient == 0 && FbTk::Menu::focused() == 0) {
#ifdef DEBUG
cerr<<__FILE__<<"("<<__FUNCTION__<<") Focus out is not a FluxboxWindow !!"<<endl;
#endif // DEBUG
} else if (winclient && (winclient == FocusControl::focusedWindow() ||
FocusControl::focusedWindow() == 0) &&
(winclient->fbwindow() == 0
|| !winclient->fbwindow()->isMoving())) {
if (winclient && (winclient == FocusControl::focusedWindow() ||
FocusControl::focusedWindow() == 0) &&
// we don't unfocus a moving window
FocusControl::setFocusedWindow(0);
m_revert_screen = &winclient->screen();
m_revert_timer.start();
}
(winclient->fbwindow() == 0 || !winclient->fbwindow()->isMoving()))
revertFocus();
}
break;
case ClientMessage:
@ -1166,8 +1136,6 @@ void Fluxbox::update(FbTk::Subject *changedsub) {
FocusControl::unfocusWindow(*client);
// make sure nothing else uses this window before focus reverts
FocusControl::setFocusedWindow(0);
m_revert_screen = &screen;
m_revert_timer.start();
}
screen.removeClient(*client);
@ -1640,22 +1608,36 @@ void Fluxbox::timed_reconfigure() {
m_reconfigure_wait = m_reread_menu_wait = false;
}
void Fluxbox::revert_focus() {
if (!m_revert_screen || FocusControl::focusedWindow() ||
FbTk::Menu::focused() || m_showing_dialog)
return;
void Fluxbox::revertFocus() {
bool revert = m_keyscreen && !m_showing_dialog;
Window win;
int revert;
Display *disp = display();
if (revert) {
// see if there are any more focus events in the queue
XEvent ev;
while (XCheckMaskEvent(display(), FocusChangeMask, &ev)) {
handleEvent(&ev);
revert = false;
}
if (!revert)
return; // already handled
}
XGetInputFocus(disp, &win, &revert);
if (revert) {
Window win;
int blah;
XGetInputFocus(display(), &win, &blah);
// we only want to revert focus if it's left dangling, as some other
// application may have set the focus to an unmanaged window
if (win == None || win == PointerRoot ||
win == m_revert_screen->rootWindow().window())
FocusControl::revertFocus(*m_revert_screen);
// we only want to revert focus if it's left dangling, as some other
// application may have set the focus to an unmanaged window
if (win != None && win != PointerRoot &&
win != m_keyscreen->rootWindow().window())
revert = false;
}
if (revert)
FocusControl::revertFocus(*m_keyscreen);
else
FocusControl::setFocusedWindow(0);
}
bool Fluxbox::validateClient(const WinClient *client) const {

View file

@ -166,7 +166,7 @@ public:
void attachSignals(WinClient &winclient);
void timed_reconfigure();
void revert_focus();
void revertFocus();
void setShowingDialog(bool value) { m_showing_dialog = value; }
bool isStartup() const { return m_starting; }
@ -267,8 +267,7 @@ private:
XEvent m_last_event;
///< when we execute reconfig command we must wait until next event round
FbTk::Timer m_reconfig_timer, m_revert_timer;
BScreen *m_revert_screen;
FbTk::Timer m_reconfig_timer;
bool m_showing_dialog;
std::auto_ptr<Keys> m_key;