+Client *Client::findModalChild(Client *skip) const
+{
+ Client *ret = 0;
+
+ // find a modal child recursively and try focus it
+ List::const_iterator it, end = _transients.end();
+ for (it = _transients.begin(); it != end; ++it)
+ if ((*it)->_modal && *it != skip)
+ return *it; // got one
+ // none of our direct children are modal, let them try check
+ for (it = _transients.begin(); it != end; ++it)
+ if ((ret = (*it)->findModalChild()))
+ return ret; // got one
+ return ret;
+}
+
+
+void Client::setModal(bool modal)
+{
+ if (modal == _modal) return;
+
+ if (modal) {
+ Client *c = this;
+ while (c->_transient_for) {
+ c = c->_transient_for;
+ if (c == this) break; // circular?
+ if (c->_modal_child) break; // already has a modal child
+ c->_modal_child = this;
+ }
+ } else {
+ // try find a replacement modal dialog
+ Client *replacement = 0;
+
+ Client *c = this;
+ while (c->_transient_for) // go up the tree
+ c = c->_transient_for;
+ replacement = c->findModalChild(this); // find a modal child, skipping this
+ assert(replacement != this);
+
+ c = this;
+ while (c->_transient_for) {
+ c = c->_transient_for;
+ if (c == this) break; // circular?
+ if (c->_modal_child != this) break; // has a different modal child
+ if (c == replacement) break; // found the replacement itself
+ c->_modal_child = replacement;
+ }
+ }
+ _modal = modal;
+}
+
+