From 7588fc10a61c141208ccccc423cc7920207b2e89 Mon Sep 17 00:00:00 2001 From: Mark Tiefenbruck Date: Tue, 1 Jan 2008 10:29:36 -0800 Subject: fix some flickering on focus change --- src/FocusControl.cc | 8 ++-- src/WinClient.cc | 1 + src/Window.cc | 25 +++++++------ src/fluxbox.cc | 104 ++++++++++++++++++++++------------------------------ src/fluxbox.hh | 5 +-- 5 files changed, 63 insertions(+), 80 deletions(-) diff --git a/src/FocusControl.cc b/src/FocusControl.cc index 426c026..184b69b 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc @@ -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()) { diff --git a/src/WinClient.cc b/src/WinClient.cc index 4ae5cad..55d6efc 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -140,6 +140,7 @@ WinClient::~WinClient() { transients.pop_back(); } + accepts_input = send_focus_message = false; if (fbwindow() != 0) fbwindow()->removeClient(*this); diff --git a/src/Window.cc b/src/Window.cc index cdfcfea..8222c06 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -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; } diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 341fda8..b96b0a2 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -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 revert_cmd(new FbTk::SimpleCommand(*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"<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 !!"<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_keyscreen->rootWindow().window()) + revert = false; + } - // 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); + if (revert) + FocusControl::revertFocus(*m_keyscreen); + else + FocusControl::setFocusedWindow(0); } bool Fluxbox::validateClient(const WinClient *client) const { diff --git a/src/fluxbox.hh b/src/fluxbox.hh index 8dac8ed..ea529e9 100644 --- a/src/fluxbox.hh +++ b/src/fluxbox.hh @@ -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 m_key; -- cgit v0.11.2