fix focus and raising for transient windows in particular
@@ -14,13 +14,9 @@
* 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?@@ -77,6 +73,12 @@
* If you toggle a setting in the configuration-menu the notch does not 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
@@ -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
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 "EventHandler.hh"
#include "RefCount.hh" #include "Command.hh" #include "Observer.hh" -#include "XLayerItem.hh" #include "FbPixmap.hh" #include "MenuTheme.hh"
@@ -20,7 +20,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@ item.setLayer(*m_layers[layernum]);
} void MultLayers::restack() { + if (!isUpdatable()) + return; int layernum=0, winnum=0, size = this->size();
@@ -20,7 +20,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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,8 +59,14 @@
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<XLayer *> m_layers; + + int m_lock; };
@@ -20,7 +20,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@
} void XLayer::restack() { + if (!m_manager.isUpdatable()) + return; + int num_windows = countWindows(); // each LayerItem can contain several windows@@ -78,6 +81,8 @@
// 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();
@@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@ normal_hint_flags(0),
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 @@ if (win == window())
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 @@ }
} return false; } + +void WinClient::addModal() { + ++m_modal; + if (transient_for) + transient_for->addModal(); +} + +void WinClient::removeModal() { + --m_modal; + if (transient_for) + transient_for->removeModal(); +}
@@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@ const WinClient *transientFor() const { return transient_for; }
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 @@
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;
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@ // TODO: should we also check if it is the active client?
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 @@ // TODO: should we also check if it is the active client?
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 @@ // TODO: should we also check if it is the active client?
tempRaiseFluxboxWindow(*(*it)->fbwindow()); } win.oplock = false; + + if (!win.winClient().transientList().empty()) + win.screen().layerManager().unlock(); + } class SetClientCmd:public FbTk::Command {@@ -1107,8 +1129,6 @@
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 @@ for (; it != it_end; ++it) {
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(); + return false; + } - if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus()) - && screen().doAutoRaise()) - m_timer.start(); + if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus()) + && screen().doAutoRaise()) + m_timer.start(); - ret = true; - } - - return ret; + return true; } void FluxboxWindow::hide() {@@ -1224,8 +1233,9 @@ }
frame().show(); - if (was_iconic && screen().doFocusNew()) + if (was_iconic && screen().doFocusNew()) { setInputFocus(); + } if (focused != frame().focused()) frame().setFocus(focused);@@ -1579,9 +1589,11 @@ // Record focus timestamp for window cycling enhancements
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 @@ return;
setState(NormalState); - if (client->isTransient() || screen().doFocusNew()) + if (client->isTransient() || screen().doFocusNew()) { setInputFocus(); + } else setFocusFlag(false);@@ -2555,8 +2568,9 @@ XCheckIfEvent(display, &dummy, queueScanner, (char *) &sa);
// 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); + } } } }
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// 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 @@ e->xfocus.detail == NotifyPointer)
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 @@ if (win == 0 && FbTk::Menu::focused() == 0) {
#ifdef DEBUG cerr<<__FILE__<<"("<<__FUNCTION__<<") Focus out is not a FluxboxWindow !!"<<endl; #endif // DEBUG - if (getFocusedWindow()) - getFocusedWindow()->setInputFocus(); + } } break;@@ -1084,8 +1085,9 @@ screen->changeWorkspaceID(ce.data.l[0]);
} 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);