From 037bd174bfb107fef4657c949ce49c188090f3e7 Mon Sep 17 00:00:00 2001 From: rathnor Date: Sun, 20 Jul 2003 18:05:40 +0000 Subject: fix focus and raising for transient windows in particular --- BUGS | 12 +++++---- ChangeLog | 3 +++ src/FbTk/Menu.hh | 3 +-- src/FbTk/MultLayers.cc | 8 ++++-- src/FbTk/MultLayers.hh | 8 +++++- src/FbTk/XLayer.cc | 7 ++++- src/WinClient.cc | 21 ++++++++++++--- src/WinClient.hh | 11 +++++--- src/Window.cc | 70 ++++++++++++++++++++++++++++++-------------------- src/fluxbox.cc | 12 +++++---- 10 files changed, 104 insertions(+), 51 deletions(-) diff --git a/BUGS b/BUGS index 0ceb3ac..8250bbd 100644 --- a/BUGS +++ b/BUGS @@ -14,14 +14,10 @@ BUGS: * After startup the font of the toolbar is to big; reload config works around this. => is this fixed now?? (as of ResourceManager changes) + => Don't think so, extra info = seems to happen for Multiple screens * Saving of number of workspaces on restart - * Multiple transients: - in openoffice - focus jumps between until user does something - in mozilla - alt-tabbing does strange thigns with other transient - layer-wise (other transient flashes) - * gaim (0.64) crashes when remembering dimensions... is this a gaim bug? @@ -78,6 +74,12 @@ Fixed bugs (or not-our-fault bugs): indicate the change until you point to another option. => Fixed + * Multiple transients: + in openoffice - focus jumps between until user does something + in mozilla - alt-tabbing does strange thigns with other transient + layer-wise (other transient flashes) + => fixed + ------------------------------ Core dumps and notes diff --git a/ChangeLog b/ChangeLog index 50bebe3..5622ba0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ (Format: Year/Month/Day) Changes for 0.9.5: *03/07/20: + * Fix aspects of focus and raising, including transients (Simon) + - fixes focus toggling with transients and sloppy focus + WinClient.hh/cc Window.cc fluxbox.cc MultLayers.hh/cc XLayer.hh/cc Menu.hh * Fix menu [re]drawing, particularly when selecting options (Simon) Menu.hh/cc * Fix disappearing Remember menu, plus titles of sub-window menus diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 9ab69b4..fba7ae2 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Menu.hh,v 1.21 2003/07/20 10:41:56 rathnor Exp $ +// $Id: Menu.hh,v 1.22 2003/07/20 18:05:39 rathnor Exp $ #ifndef FBTK_MENU_HH #define FBTK_MENU_HH @@ -37,7 +37,6 @@ #include "RefCount.hh" #include "Command.hh" #include "Observer.hh" -#include "XLayerItem.hh" #include "FbPixmap.hh" #include "MenuTheme.hh" diff --git a/src/FbTk/MultLayers.cc b/src/FbTk/MultLayers.cc index fea4dae..9e3272b 100644 --- a/src/FbTk/MultLayers.cc +++ b/src/FbTk/MultLayers.cc @@ -20,7 +20,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: MultLayers.cc,v 1.6 2003/02/18 15:08:12 rathnor Exp $ +// $Id: MultLayers.cc,v 1.7 2003/07/20 18:05:39 rathnor Exp $ #include "MultLayers.hh" #include "XLayer.hh" @@ -32,7 +32,9 @@ using namespace std; using namespace FbTk; -MultLayers::MultLayers(int numlayers) { +MultLayers::MultLayers(int numlayers) : + m_lock(0) +{ for (int i=0; i < numlayers; ++i) m_layers.push_back(new XLayer(*this, i)); } @@ -150,6 +152,8 @@ void MultLayers::moveToLayer(XLayerItem &item, int layernum) { } void MultLayers::restack() { + if (!isUpdatable()) + return; int layernum=0, winnum=0, size = this->size(); diff --git a/src/FbTk/MultLayers.hh b/src/FbTk/MultLayers.hh index 5cfc731..29c80a8 100644 --- a/src/FbTk/MultLayers.hh +++ b/src/FbTk/MultLayers.hh @@ -20,7 +20,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: MultLayers.hh,v 1.5 2003/02/09 14:11:14 rathnor Exp $ +// $Id: MultLayers.hh,v 1.6 2003/07/20 18:05:40 rathnor Exp $ #ifndef FBTK_MULTLAYERS_HH #define FBTK_MULTLAYERS_HH @@ -59,9 +59,15 @@ public: XLayer *getLayer(size_t num); const XLayer *getLayer(size_t num) const; + inline bool isUpdatable() const { return m_lock == 0; } + inline void lock() { ++m_lock; } + inline void unlock() { if (--m_lock == 0) restack(); } + private: std::vector m_layers; + int m_lock; + }; }; diff --git a/src/FbTk/XLayer.cc b/src/FbTk/XLayer.cc index 023a80d..8164444 100644 --- a/src/FbTk/XLayer.cc +++ b/src/FbTk/XLayer.cc @@ -20,7 +20,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: XLayer.cc,v 1.8 2003/04/15 23:20:31 rathnor Exp $ +// $Id: XLayer.cc,v 1.9 2003/07/20 18:05:40 rathnor Exp $ #include "XLayer.hh" #include "XLayerItem.hh" @@ -39,6 +39,9 @@ XLayer::~XLayer() { } void XLayer::restack() { + if (!m_manager.isUpdatable()) + return; + int num_windows = countWindows(); // each LayerItem can contain several windows @@ -78,6 +81,8 @@ int XLayer::countWindows() { // Stack all windows associated with 'item' below the 'above' item void XLayer::stackBelowItem(XLayerItem *item, XLayerItem *above) { + if (!m_manager.isUpdatable()) + return; Window *winlist; size_t winnum, size, num = item->numWindows(); diff --git a/src/WinClient.cc b/src/WinClient.cc index ddd3cd1..416dd63 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: WinClient.cc,v 1.17 2003/07/10 11:58:13 fluxgen Exp $ +// $Id: WinClient.cc,v 1.18 2003/07/20 18:05:39 rathnor Exp $ #include "WinClient.hh" @@ -54,7 +54,7 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb wm_hint_flags(0), send_focus_message(false), m_win(fbwin), - modal(false), + m_modal(0), m_title(""), m_icon_title(""), m_class_name(""), m_instance_name(""), m_blackbox_hint(0), @@ -245,8 +245,9 @@ void WinClient::updateTransientInfo() { return; if (win != None && m_win->screen().rootWindow() == win) { - modal = true; - return; // transient for root window... + // transient for root window... = transient for group + // I don't think we are group-aware yet + return; } FluxboxWindow *transient_win = Fluxbox::instance()->searchWindow(win); @@ -514,3 +515,15 @@ bool WinClient::hasGroupLeftWindow() const { } return false; } + +void WinClient::addModal() { + ++m_modal; + if (transient_for) + transient_for->addModal(); +} + +void WinClient::removeModal() { + --m_modal; + if (transient_for) + transient_for->removeModal(); +} diff --git a/src/WinClient.hh b/src/WinClient.hh index c72208f..cedbdd7 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: WinClient.hh,v 1.8 2003/06/23 14:16:05 rathnor Exp $ +// $Id: WinClient.hh,v 1.9 2003/07/20 18:05:39 rathnor Exp $ #ifndef WINCLIENT_HH #define WINCLIENT_HH @@ -70,7 +70,10 @@ public: TransientList &transientList() { return transients; } const TransientList &transientList() const { return transients; } bool isTransient() const { return transient_for != 0; } - bool isModal() const { return modal; } + + bool isModal() const { return m_modal > 0; } + void addModal(); // some transient of ours (or us) is modal + void removeModal(); // some transient (or us) is no longer modal bool operator == (const FluxboxWindow &win) const { return (m_win == &win); @@ -138,7 +141,9 @@ public: enum { F_NOINPUT = 0, F_PASSIVE, F_LOCALLYACTIVE, F_GLOBALLYACTIVE }; private: - bool modal; + // number of transients which we are modal for + // or indicates that we are modal if don't have any transients + int m_modal; std::string m_title, m_icon_title; std::string m_class_name, m_instance_name; diff --git a/src/Window.cc b/src/Window.cc index bfb7dae..4e45370 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Window.cc,v 1.206 2003/07/20 08:12:36 rathnor Exp $ +// $Id: Window.cc,v 1.207 2003/07/20 18:05:39 rathnor Exp $ #include "Window.hh" @@ -145,6 +145,11 @@ void raiseFluxboxWindow(FluxboxWindow &win) { if (win.oplock) return; win.oplock = true; + // we need to lock actual restacking so that raising above active transient + // won't do anything nasty + if (!win.winClient().transientList().empty()) + win.screen().layerManager().lock(); + if (!win.isIconic()) { win.screen().updateNetizenWindowRaise(win.clientWindow()); win.layerItem().raise(); @@ -159,6 +164,9 @@ void raiseFluxboxWindow(FluxboxWindow &win) { raiseFluxboxWindow(*(*it)->fbwindow()); } win.oplock = false; + + if (!win.winClient().transientList().empty()) + win.screen().layerManager().unlock(); } /// lower window and do the same for each transient it holds @@ -166,6 +174,11 @@ void lowerFluxboxWindow(FluxboxWindow &win) { if (win.oplock) return; win.oplock = true; + // we need to lock actual restacking so that raising above active transient + // won't do anything nasty + if (!win.winClient().transientList().empty()) + win.screen().layerManager().lock(); + if (!win.isIconic()) { win.screen().updateNetizenWindowLower(win.clientWindow()); win.layerItem().lower(); @@ -179,6 +192,8 @@ void lowerFluxboxWindow(FluxboxWindow &win) { lowerFluxboxWindow(*(*it)->fbwindow()); } win.oplock = false; + if (!win.winClient().transientList().empty()) + win.screen().layerManager().unlock(); } /// raise window and do the same for each transient it holds @@ -186,6 +201,9 @@ void tempRaiseFluxboxWindow(FluxboxWindow &win) { if (win.oplock) return; win.oplock = true; + if (!win.winClient().transientList().empty()) + win.screen().layerManager().lock(); + if (!win.isIconic()) { // don't update netizen, as it is only temporary win.layerItem().tempRaise(); @@ -200,6 +218,10 @@ void tempRaiseFluxboxWindow(FluxboxWindow &win) { tempRaiseFluxboxWindow(*(*it)->fbwindow()); } win.oplock = false; + + if (!win.winClient().transientList().empty()) + win.screen().layerManager().unlock(); + } class SetClientCmd:public FbTk::Command { @@ -1107,8 +1129,6 @@ bool FluxboxWindow::setInputFocus() { if (! validateClient()) return false; - bool ret = false; - if (!m_client->transients.empty() && m_client->isModal()) { WinClient::TransientList::iterator it = m_client->transients.begin(); WinClient::TransientList::iterator it_end = m_client->transients.end(); @@ -1116,30 +1136,19 @@ bool FluxboxWindow::setInputFocus() { if ((*it)->isModal()) return (*it)->fbwindow()->setCurrentClient(**it, true); } + } + if (m_client->getFocusMode() == WinClient::F_LOCALLYACTIVE || + m_client->getFocusMode() == WinClient::F_PASSIVE) { + m_client->setInputFocus(RevertToPointerRoot, CurrentTime); } else { - if (m_client->getFocusMode() == WinClient::F_LOCALLYACTIVE || - m_client->getFocusMode() == WinClient::F_PASSIVE) { - m_client->setInputFocus(RevertToPointerRoot, CurrentTime); - } else { - return false; - } - - screen().setFocusedWindow(*m_client); - - Fluxbox::instance()->setFocusedWindow(this); - - frame().setFocus(true); - - m_client->sendFocus(); - - if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus()) - && screen().doAutoRaise()) - m_timer.start(); - - ret = true; + return false; } - return ret; + if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus()) + && screen().doAutoRaise()) + m_timer.start(); + + return true; } void FluxboxWindow::hide() { @@ -1224,8 +1233,9 @@ void FluxboxWindow::deiconify(bool reassoc, bool do_raise) { frame().show(); - if (was_iconic && screen().doFocusNew()) + if (was_iconic && screen().doFocusNew()) { setInputFocus(); + } if (focused != frame().focused()) frame().setFocus(focused); @@ -1579,9 +1589,11 @@ void FluxboxWindow::setFocusFlag(bool focus) { if (focused) gettimeofday(&m_last_focus_time, 0); + screen().setFocusedWindow(*m_client); + m_client->sendFocus(); frame().setFocus(focus); - if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus()) && + if (!focused && (screen().isSloppyFocus() || screen().isSemiSloppyFocus()) && screen().doAutoRaise()) m_timer.stop(); } @@ -2042,8 +2054,9 @@ void FluxboxWindow::mapNotifyEvent(XMapEvent &ne) { setState(NormalState); - if (client->isTransient() || screen().doFocusNew()) + if (client->isTransient() || screen().doFocusNew()) { setInputFocus(); + } else setFocusFlag(false); @@ -2555,8 +2568,9 @@ void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) { // if client is set, use setCurrent client, otherwise just setInputFocus if ((!sa.leave || sa.inferior) && - ((client && setCurrentClient(*client, true)) || setInputFocus())) + ((client && setCurrentClient(*client, true)) || setInputFocus())) { installColormap(True); + } } } } diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 027da76..b7a4d5b 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: fluxbox.cc,v 1.171 2003/07/18 15:40:55 rathnor Exp $ +// $Id: fluxbox.cc,v 1.172 2003/07/20 18:05:39 rathnor Exp $ #include "fluxbox.hh" @@ -891,11 +891,13 @@ void Fluxbox::handleEvent(XEvent * const e) { break; FluxboxWindow *win = searchWindow(e->xfocus.window); - if (win && ! win->isFocused()) + if (win && ! win->isFocused()) { setFocusedWindow(win); + } } break; case FocusOut:{ + if (e->xfocus.mode == NotifyUngrab || e->xfocus.detail == NotifyPointer) break; @@ -904,8 +906,7 @@ void Fluxbox::handleEvent(XEvent * const e) { #ifdef DEBUG cerr<<__FILE__<<"("<<__FUNCTION__<<") Focus out is not a FluxboxWindow !!"<setInputFocus(); + } } break; @@ -1084,8 +1085,9 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) { } else if (ce.message_type == m_fbatoms->getFluxboxChangeWindowFocusAtom()) { FluxboxWindow *win = searchWindow(ce.window); - if (win && win->isVisible() && win->setInputFocus()) + if (win && win->isVisible() && win->setInputFocus()) { win->installColormap(true); + } } else if (ce.message_type == m_fbatoms->getFluxboxCycleWindowFocusAtom()) { BScreen *screen = searchScreen(ce.window); -- cgit v0.11.2