fixed implementation of _NET_WM_STATE_MODAL
markt markt
6 files changed,
51 insertions(+),
23 deletions(-)
M
ChangeLog
→
ChangeLog
@@ -1,6 +1,8 @@
(Format: Year/Month/Day) Changes for 1.0.0: *07/06/30: + * Fixed implementation of _NET_WM_STATE_MODAL (Mark) + Ewmh.cc/hh WinClient.cc/hh Window.cc * Fixed the groups file, even though it's deprecated (Mark) Workspace.cc Screen.cc * Fix _NET_WM_STATE_DEMANDS_ATTENTION with tabbed windows, #1732392 (Mark)
M
src/Ewmh.cc
→
src/Ewmh.cc
@@ -629,7 +629,7 @@ if (win.isIconHidden())
state.push_back(m_net_wm_state_skip_taskbar); if (win.isFullscreen()) state.push_back(m_net_wm_state_fullscreen); - if (win.winClient().isModal()) + if (win.winClient().isStateModal()) state.push_back(m_net_wm_state_modal); FluxboxWindow::ClientList::iterator it = win.clientList().begin();@@ -1031,10 +1031,14 @@ m_net_wm_ping = XInternAtom(disp, "_NET_WM_PING", False);
utf8_string = XInternAtom(disp, "UTF8_STRING", False); } -// wrapper for avoiding changing every AtomHandler to include an unnecessary -// parameter, although we need it for _NET_WM_STATE_DEMANDS_ATTENTION +// wrapper for real setState, since most operations don't need the client void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { setState(win, state, value, win.winClient()); +} + +// wrapper for real toggleState, since most operations don't need the client +void Ewmh::toggleState(FluxboxWindow &win, Atom state) { + toggleState(win, state, win.winClient()); } // set window state@@ -1084,13 +1088,14 @@ } else { // erase it
Fluxbox::instance()->attentionHandler(). update(&client.focusSig()); } + } else if (state == m_net_wm_state_modal) { + client.setStateModal(value); } - // Note: state == net_wm_state_modal, We should not change it } // toggle window state -void Ewmh::toggleState(FluxboxWindow &win, Atom state) { +void Ewmh::toggleState(FluxboxWindow &win, Atom state, WinClient &client) { if (state == m_net_wm_state_sticky) { // sticky win.stick(); } else if (state == m_net_wm_state_shaded){ // shaded@@ -1119,6 +1124,8 @@ if (win.layerNum() == Layer::ABOVE_DOCK)
win.moveToLayer(Layer::NORMAL); else win.moveToLayer(Layer::ABOVE_DOCK); + } else if (state == m_net_wm_state_modal) { // modal + client.setStateModal(!client.isStateModal()); } }
M
src/Ewmh.hh
→
src/Ewmh.hh
@@ -70,6 +70,7 @@ void setState(FluxboxWindow &win, Atom state, bool value);
void setState(FluxboxWindow &win, Atom state, bool value, WinClient &client); void toggleState(FluxboxWindow &win, Atom state); + void toggleState(FluxboxWindow &win, Atom state, WinClient &client); void createAtoms(); void updateStrut(WinClient &winclient); void updateActions(FluxboxWindow &win);
M
src/WinClient.cc
→
src/WinClient.cc
@@ -76,7 +76,8 @@ initial_state(0),
normal_hint_flags(0), wm_hint_flags(0), m_win(fbwin), - m_modal(0), + m_modal_count(0), + m_modal(false), send_focus_message(false), send_close_message(false), m_win_gravity(0),@@ -136,13 +137,14 @@ m_diesig.notify();
Fluxbox *fluxbox = Fluxbox::instance(); - // // clear transients and transient_for // if (transient_for != 0) { assert(transient_for != this); transient_for->transientList().remove(this); + if (m_modal) + transient_for->removeModal(); transient_for = 0; }@@ -276,6 +278,8 @@ void WinClient::updateTransientInfo() {
// remove this from parent if (transientFor() != 0) { transientFor()->transientList().remove(this); + if (m_modal) + transientFor()->removeModal(); } transient_for = 0;@@ -337,6 +341,8 @@ if (transientFor() != 0) {
// we need to add ourself to the right client in // the transientFor() window so we search client transient_for->transientList().push_back(this); + if (m_modal) + transient_for->addModal(); } }@@ -663,16 +669,21 @@
return false; } -void WinClient::addModal() { - ++m_modal; - if (transient_for) - transient_for->addModal(); -} +void WinClient::setStateModal(bool state) { + if (state == m_modal) + return; + + m_modal = state; + if (transient_for) { + if (state) + transient_for->addModal(); + else + transient_for->removeModal(); + } -void WinClient::removeModal() { - --m_modal; - if (transient_for) - transient_for->removeModal(); + // TODO: we're not implementing the following part of EWMH spec: + // "if WM_TRANSIENT_FOR is not set or set to the root window the dialog is + // modal for its window group." } bool WinClient::validateClient() const {
M
src/WinClient.hh
→
src/WinClient.hh
@@ -57,9 +57,6 @@ void sendClose(bool forceful = false);
// not aware of anything that makes this false at present inline bool isClosable() const { return true; } - void addModal(); // some transient of ours (or us) is modal - void removeModal(); // some transient (or us) is no longer modal - /// updates from wm class hints void updateWMClassHint(); void updateWMProtocols();@@ -127,7 +124,9 @@ inline TransientList &transientList() { return transients; }
inline const TransientList &transientList() const { return transients; } inline bool isTransient() const { return transient_for != 0; } - inline bool isModal() const { return m_modal > 0; } + inline bool isModal() const { return m_modal_count > 0; } + inline bool isStateModal() const { return m_modal; } + void setStateModal(bool state); const FbTk::FbPixmap &iconPixmap() const { return m_icon_pixmap; } const FbTk::FbPixmap &iconMask() const { return m_icon_mask; }@@ -188,11 +187,16 @@ private:
/// removes client from any waiting list and clears empty waiting lists void removeTransientFromWaitingList(); + // some transient of ours (or us) is modal + void addModal() { ++m_modal_count; } + // some transient (or us) is no longer modal + void removeModal() { --m_modal_count; } + FluxboxWindow *m_win; // number of transients which we are modal for - // or indicates that we are modal if don't have any transients - int m_modal; + int m_modal_count; + bool m_modal; bool send_focus_message, send_close_message; int m_win_gravity;
M
src/Window.cc
→
src/Window.cc
@@ -1372,10 +1372,13 @@ for (; it != it_end; ++it) {
#ifdef DEBUG cerr<<__FUNCTION__<<": transient 0x"<<(*it)<<endl; #endif // DEBUG - if ((*it)->isModal()) + if ((*it)->isStateModal()) return (*it)->focus(); } } + + if (m_client->isModal()) + return false; bool ret = false;