fix some issues with reverting focus
@@ -45,6 +45,7 @@ using std::string;
WinClient *FocusControl::s_focused_window = 0; FluxboxWindow *FocusControl::s_focused_fbwindow = 0; +WinClient *FocusControl::s_expecting_focus = 0; bool FocusControl::s_reverting = false; namespace {@@ -242,7 +243,7 @@ * If workspace is outside the ID range, then the absolute last focused window
* is given. */ Focusable *FocusControl::lastFocusedWindow(int workspace) { - if (m_focused_list.empty() || m_screen.isShuttingdown()) return 0; + if (m_screen.isShuttingdown()) return 0; if (workspace < 0 || workspace >= (int) m_screen.numberOfWorkspaces()) return m_focused_list.clientList().front();@@ -250,6 +251,7 @@ 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() && (*it)->acceptsFocus() && + (*it)->fbwindow()->winClient().validateClient() && ((((int)(*it)->fbwindow()->workspaceNumber()) == workspace || (*it)->fbwindow()->isStuck()) && !(*it)->fbwindow()->isIconic())) return *it;@@ -536,6 +538,7 @@ if (client && client->fbwindow() && !client->fbwindow()->isIconic()) {
// screen should be ok s_focused_fbwindow = client->fbwindow(); s_focused_window = client; // update focused window + s_expecting_focus = 0; s_focused_fbwindow->setCurrentClient(*client, false); // don't set inputfocus s_focused_fbwindow->setFocusFlag(true); // set focus flag
@@ -134,8 +134,10 @@ // like revertFocus, but specifically related to this window (transients etc)
static void unfocusWindow(WinClient &client, bool full_revert = true, bool unfocus_frame = false); static void setFocusedWindow(WinClient *focus_to); static void setFocusedFbWindow(FluxboxWindow *focus_to) { s_focused_fbwindow = focus_to; } + static void setExpectingFocus(WinClient *client) { s_expecting_focus = client; } static WinClient *focusedWindow() { return s_focused_window; } static FluxboxWindow *focusedFbWindow() { return s_focused_fbwindow; } + static WinClient *expectingFocus() { return s_expecting_focus; } private: BScreen &m_screen;@@ -158,6 +160,7 @@ WinClient *m_cycling_last;
static WinClient *s_focused_window; static FluxboxWindow *s_focused_fbwindow; + static WinClient *s_expecting_focus; static bool s_reverting; };
@@ -30,7 +30,6 @@ #include "WorkspaceNameTool.hh"
#include "ArrowButton.hh" // Themes -#include "IconbarTheme.hh" #include "WorkspaceNameTheme.hh" #include "ButtonTheme.hh"
@@ -174,7 +174,8 @@ }
bool WinClient::sendFocus() { if (accepts_input) { - setInputFocus(RevertToParent, CurrentTime); + setInputFocus(RevertToPointerRoot, CurrentTime); + FocusControl::setExpectingFocus(this); return true; } if (!send_focus_message)@@ -198,6 +199,7 @@ ce.xclient.data.l[3] = 0l;
ce.xclient.data.l[4] = 0l; // send focus msg XSendEvent(display(), window(), false, NoEventMask, &ce); + FocusControl::setExpectingFocus(this); return true; }
@@ -2353,8 +2353,9 @@ if (de.window == m_client->window()) {
#ifdef DEBUG cerr<<__FILE__<<"("<<__LINE__<<"): DestroyNotifyEvent this="<<this<<" title = "<<title()<<endl; #endif // DEBUG - if (numClients() == 1) - hide(); + delete m_client; + if (numClients() == 0) + delete this; } }@@ -3680,9 +3681,8 @@ #ifdef DEBUG
cerr<<"FluxboxWindow::restore: remap = "<<remap<<endl; cerr<<__FILE__<<"("<<__FUNCTION__<<"): numClients() = "<<numClients()<<endl; #endif // DEBUG - if (numClients() == 0) { - hide(true); - } + if (numClients() == 0) + delete this; }
@@ -749,11 +749,6 @@ if (winclient != 0) {
FluxboxWindow *win = winclient->fbwindow(); if (win) win->destroyNotifyEvent(e->xdestroywindow); - - delete winclient; - - if (win && win->numClients() == 0) - delete win; } }@@ -835,10 +830,11 @@ e->xfocus.detail == NotifyInferior)
break; WinClient *winclient = searchWindow(e->xfocus.window); - if (winclient && (winclient == FocusControl::focusedWindow() || - FocusControl::focusedWindow() == 0) && + if ((winclient == FocusControl::focusedWindow() || + FocusControl::focusedWindow() == 0) && // we don't unfocus a moving window - (winclient->fbwindow() == 0 || !winclient->fbwindow()->isMoving())) + (!winclient || !winclient->fbwindow() || + !winclient->fbwindow()->isMoving())) revertFocus(); } break;@@ -884,13 +880,6 @@
// this should delete client and adjust m_focused_window if necessary win->unmapNotifyEvent(ue); - winclient = 0; // it's invalid now when win destroyed the client - - // finally destroy window if empty - if (win->numClients() == 0) { - delete win; - win = 0; - } } // according to http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4@@ -1077,6 +1066,9 @@ if (FocusControl::focusedWindow() == client) {
FocusControl::unfocusWindow(*client); // make sure nothing else uses this window before focus reverts FocusControl::setFocusedWindow(0); + } else if (FocusControl::expectingFocus() == client) { + FocusControl::setExpectingFocus(0); + revertFocus(); } screen.removeClient(*client);@@ -1555,22 +1547,18 @@
if (revert) { // see if there are any more focus events in the queue XEvent ev; - while (XCheckMaskEvent(display(), FocusChangeMask, &ev)) { + while (XCheckMaskEvent(display(), FocusChangeMask, &ev)) handleEvent(&ev); - revert = false; - } - if (!revert) + if (FocusControl::focusedWindow() || FocusControl::expectingFocus()) return; // already handled - } - 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 && + if (win != None && win != PointerRoot && !searchWindow(win) && win != m_keyscreen->rootWindow().window()) revert = false; }