diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | src/Ewmh.cc | 17 | ||||
-rw-r--r-- | src/Ewmh.hh | 1 | ||||
-rw-r--r-- | src/WinClient.cc | 33 | ||||
-rw-r--r-- | src/WinClient.hh | 16 | ||||
-rw-r--r-- | src/Window.cc | 5 |
6 files changed, 51 insertions, 23 deletions
@@ -1,6 +1,8 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0.0: | 2 | Changes for 1.0.0: |
3 | *07/06/30: | 3 | *07/06/30: |
4 | * Fixed implementation of _NET_WM_STATE_MODAL (Mark) | ||
5 | Ewmh.cc/hh WinClient.cc/hh Window.cc | ||
4 | * Fixed the groups file, even though it's deprecated (Mark) | 6 | * Fixed the groups file, even though it's deprecated (Mark) |
5 | Workspace.cc Screen.cc | 7 | Workspace.cc Screen.cc |
6 | * Fix _NET_WM_STATE_DEMANDS_ATTENTION with tabbed windows, #1732392 (Mark) | 8 | * Fix _NET_WM_STATE_DEMANDS_ATTENTION with tabbed windows, #1732392 (Mark) |
diff --git a/src/Ewmh.cc b/src/Ewmh.cc index b4e831d..ef2fc09 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc | |||
@@ -629,7 +629,7 @@ void Ewmh::updateState(FluxboxWindow &win) { | |||
629 | state.push_back(m_net_wm_state_skip_taskbar); | 629 | state.push_back(m_net_wm_state_skip_taskbar); |
630 | if (win.isFullscreen()) | 630 | if (win.isFullscreen()) |
631 | state.push_back(m_net_wm_state_fullscreen); | 631 | state.push_back(m_net_wm_state_fullscreen); |
632 | if (win.winClient().isModal()) | 632 | if (win.winClient().isStateModal()) |
633 | state.push_back(m_net_wm_state_modal); | 633 | state.push_back(m_net_wm_state_modal); |
634 | 634 | ||
635 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); | 635 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); |
@@ -1031,12 +1031,16 @@ void Ewmh::createAtoms() { | |||
1031 | utf8_string = XInternAtom(disp, "UTF8_STRING", False); | 1031 | utf8_string = XInternAtom(disp, "UTF8_STRING", False); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | // wrapper for avoiding changing every AtomHandler to include an unnecessary | 1034 | // wrapper for real setState, since most operations don't need the client |
1035 | // parameter, although we need it for _NET_WM_STATE_DEMANDS_ATTENTION | ||
1036 | void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { | 1035 | void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { |
1037 | setState(win, state, value, win.winClient()); | 1036 | setState(win, state, value, win.winClient()); |
1038 | } | 1037 | } |
1039 | 1038 | ||
1039 | // wrapper for real toggleState, since most operations don't need the client | ||
1040 | void Ewmh::toggleState(FluxboxWindow &win, Atom state) { | ||
1041 | toggleState(win, state, win.winClient()); | ||
1042 | } | ||
1043 | |||
1040 | // set window state | 1044 | // set window state |
1041 | void Ewmh::setState(FluxboxWindow &win, Atom state, bool value, | 1045 | void Ewmh::setState(FluxboxWindow &win, Atom state, bool value, |
1042 | WinClient &client) { | 1046 | WinClient &client) { |
@@ -1084,13 +1088,14 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value, | |||
1084 | Fluxbox::instance()->attentionHandler(). | 1088 | Fluxbox::instance()->attentionHandler(). |
1085 | update(&client.focusSig()); | 1089 | update(&client.focusSig()); |
1086 | } | 1090 | } |
1091 | } else if (state == m_net_wm_state_modal) { | ||
1092 | client.setStateModal(value); | ||
1087 | } | 1093 | } |
1088 | 1094 | ||
1089 | // Note: state == net_wm_state_modal, We should not change it | ||
1090 | } | 1095 | } |
1091 | 1096 | ||
1092 | // toggle window state | 1097 | // toggle window state |
1093 | void Ewmh::toggleState(FluxboxWindow &win, Atom state) { | 1098 | void Ewmh::toggleState(FluxboxWindow &win, Atom state, WinClient &client) { |
1094 | if (state == m_net_wm_state_sticky) { // sticky | 1099 | if (state == m_net_wm_state_sticky) { // sticky |
1095 | win.stick(); | 1100 | win.stick(); |
1096 | } else if (state == m_net_wm_state_shaded){ // shaded | 1101 | } else if (state == m_net_wm_state_shaded){ // shaded |
@@ -1119,6 +1124,8 @@ void Ewmh::toggleState(FluxboxWindow &win, Atom state) { | |||
1119 | win.moveToLayer(Layer::NORMAL); | 1124 | win.moveToLayer(Layer::NORMAL); |
1120 | else | 1125 | else |
1121 | win.moveToLayer(Layer::ABOVE_DOCK); | 1126 | win.moveToLayer(Layer::ABOVE_DOCK); |
1127 | } else if (state == m_net_wm_state_modal) { // modal | ||
1128 | client.setStateModal(!client.isStateModal()); | ||
1122 | } | 1129 | } |
1123 | 1130 | ||
1124 | } | 1131 | } |
diff --git a/src/Ewmh.hh b/src/Ewmh.hh index c1a6868..00979a1 100644 --- a/src/Ewmh.hh +++ b/src/Ewmh.hh | |||
@@ -70,6 +70,7 @@ private: | |||
70 | void setState(FluxboxWindow &win, Atom state, bool value, | 70 | void setState(FluxboxWindow &win, Atom state, bool value, |
71 | WinClient &client); | 71 | WinClient &client); |
72 | void toggleState(FluxboxWindow &win, Atom state); | 72 | void toggleState(FluxboxWindow &win, Atom state); |
73 | void toggleState(FluxboxWindow &win, Atom state, WinClient &client); | ||
73 | void createAtoms(); | 74 | void createAtoms(); |
74 | void updateStrut(WinClient &winclient); | 75 | void updateStrut(WinClient &winclient); |
75 | void updateActions(FluxboxWindow &win); | 76 | void updateActions(FluxboxWindow &win); |
diff --git a/src/WinClient.cc b/src/WinClient.cc index 250a0b8..fd1944b 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc | |||
@@ -76,7 +76,8 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb | |||
76 | normal_hint_flags(0), | 76 | normal_hint_flags(0), |
77 | wm_hint_flags(0), | 77 | wm_hint_flags(0), |
78 | m_win(fbwin), | 78 | m_win(fbwin), |
79 | m_modal(0), | 79 | m_modal_count(0), |
80 | m_modal(false), | ||
80 | send_focus_message(false), | 81 | send_focus_message(false), |
81 | send_close_message(false), | 82 | send_close_message(false), |
82 | m_win_gravity(0), | 83 | m_win_gravity(0), |
@@ -136,13 +137,14 @@ WinClient::~WinClient() { | |||
136 | 137 | ||
137 | Fluxbox *fluxbox = Fluxbox::instance(); | 138 | Fluxbox *fluxbox = Fluxbox::instance(); |
138 | 139 | ||
139 | |||
140 | // | 140 | // |
141 | // clear transients and transient_for | 141 | // clear transients and transient_for |
142 | // | 142 | // |
143 | if (transient_for != 0) { | 143 | if (transient_for != 0) { |
144 | assert(transient_for != this); | 144 | assert(transient_for != this); |
145 | transient_for->transientList().remove(this); | 145 | transient_for->transientList().remove(this); |
146 | if (m_modal) | ||
147 | transient_for->removeModal(); | ||
146 | transient_for = 0; | 148 | transient_for = 0; |
147 | } | 149 | } |
148 | 150 | ||
@@ -276,6 +278,8 @@ void WinClient::updateTransientInfo() { | |||
276 | // remove this from parent | 278 | // remove this from parent |
277 | if (transientFor() != 0) { | 279 | if (transientFor() != 0) { |
278 | transientFor()->transientList().remove(this); | 280 | transientFor()->transientList().remove(this); |
281 | if (m_modal) | ||
282 | transientFor()->removeModal(); | ||
279 | } | 283 | } |
280 | 284 | ||
281 | transient_for = 0; | 285 | transient_for = 0; |
@@ -337,6 +341,8 @@ void WinClient::updateTransientInfo() { | |||
337 | // we need to add ourself to the right client in | 341 | // we need to add ourself to the right client in |
338 | // the transientFor() window so we search client | 342 | // the transientFor() window so we search client |
339 | transient_for->transientList().push_back(this); | 343 | transient_for->transientList().push_back(this); |
344 | if (m_modal) | ||
345 | transient_for->addModal(); | ||
340 | } | 346 | } |
341 | 347 | ||
342 | } | 348 | } |
@@ -663,16 +669,21 @@ bool WinClient::hasGroupLeftWindow() const { | |||
663 | return false; | 669 | return false; |
664 | } | 670 | } |
665 | 671 | ||
666 | void WinClient::addModal() { | 672 | void WinClient::setStateModal(bool state) { |
667 | ++m_modal; | 673 | if (state == m_modal) |
668 | if (transient_for) | 674 | return; |
669 | transient_for->addModal(); | 675 | |
670 | } | 676 | m_modal = state; |
677 | if (transient_for) { | ||
678 | if (state) | ||
679 | transient_for->addModal(); | ||
680 | else | ||
681 | transient_for->removeModal(); | ||
682 | } | ||
671 | 683 | ||
672 | void WinClient::removeModal() { | 684 | // TODO: we're not implementing the following part of EWMH spec: |
673 | --m_modal; | 685 | // "if WM_TRANSIENT_FOR is not set or set to the root window the dialog is |
674 | if (transient_for) | 686 | // modal for its window group." |
675 | transient_for->removeModal(); | ||
676 | } | 687 | } |
677 | 688 | ||
678 | bool WinClient::validateClient() const { | 689 | bool WinClient::validateClient() const { |
diff --git a/src/WinClient.hh b/src/WinClient.hh index 40daa8e..01517c2 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh | |||
@@ -57,9 +57,6 @@ public: | |||
57 | // not aware of anything that makes this false at present | 57 | // not aware of anything that makes this false at present |
58 | inline bool isClosable() const { return true; } | 58 | inline bool isClosable() const { return true; } |
59 | 59 | ||
60 | void addModal(); // some transient of ours (or us) is modal | ||
61 | void removeModal(); // some transient (or us) is no longer modal | ||
62 | |||
63 | /// updates from wm class hints | 60 | /// updates from wm class hints |
64 | void updateWMClassHint(); | 61 | void updateWMClassHint(); |
65 | void updateWMProtocols(); | 62 | void updateWMProtocols(); |
@@ -127,7 +124,9 @@ public: | |||
127 | inline const TransientList &transientList() const { return transients; } | 124 | inline const TransientList &transientList() const { return transients; } |
128 | inline bool isTransient() const { return transient_for != 0; } | 125 | inline bool isTransient() const { return transient_for != 0; } |
129 | 126 | ||
130 | inline bool isModal() const { return m_modal > 0; } | 127 | inline bool isModal() const { return m_modal_count > 0; } |
128 | inline bool isStateModal() const { return m_modal; } | ||
129 | void setStateModal(bool state); | ||
131 | 130 | ||
132 | const FbTk::FbPixmap &iconPixmap() const { return m_icon_pixmap; } | 131 | const FbTk::FbPixmap &iconPixmap() const { return m_icon_pixmap; } |
133 | const FbTk::FbPixmap &iconMask() const { return m_icon_mask; } | 132 | const FbTk::FbPixmap &iconMask() const { return m_icon_mask; } |
@@ -188,11 +187,16 @@ private: | |||
188 | /// removes client from any waiting list and clears empty waiting lists | 187 | /// removes client from any waiting list and clears empty waiting lists |
189 | void removeTransientFromWaitingList(); | 188 | void removeTransientFromWaitingList(); |
190 | 189 | ||
190 | // some transient of ours (or us) is modal | ||
191 | void addModal() { ++m_modal_count; } | ||
192 | // some transient (or us) is no longer modal | ||
193 | void removeModal() { --m_modal_count; } | ||
194 | |||
191 | FluxboxWindow *m_win; | 195 | FluxboxWindow *m_win; |
192 | 196 | ||
193 | // number of transients which we are modal for | 197 | // number of transients which we are modal for |
194 | // or indicates that we are modal if don't have any transients | 198 | int m_modal_count; |
195 | int m_modal; | 199 | bool m_modal; |
196 | bool send_focus_message, send_close_message; | 200 | bool send_focus_message, send_close_message; |
197 | 201 | ||
198 | int m_win_gravity; | 202 | int m_win_gravity; |
diff --git a/src/Window.cc b/src/Window.cc index 1c839f6..b44f9f7 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -1372,11 +1372,14 @@ bool FluxboxWindow::setInputFocus() { | |||
1372 | #ifdef DEBUG | 1372 | #ifdef DEBUG |
1373 | cerr<<__FUNCTION__<<": transient 0x"<<(*it)<<endl; | 1373 | cerr<<__FUNCTION__<<": transient 0x"<<(*it)<<endl; |
1374 | #endif // DEBUG | 1374 | #endif // DEBUG |
1375 | if ((*it)->isModal()) | 1375 | if ((*it)->isStateModal()) |
1376 | return (*it)->focus(); | 1376 | return (*it)->focus(); |
1377 | } | 1377 | } |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | if (m_client->isModal()) | ||
1381 | return false; | ||
1382 | |||
1380 | bool ret = false; | 1383 | bool ret = false; |
1381 | 1384 | ||
1382 | if (m_client->getFocusMode() == WinClient::F_LOCALLYACTIVE || | 1385 | if (m_client->getFocusMode() == WinClient::F_LOCALLYACTIVE || |