aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lübking <thomas.luebking@gmail.com>2016-06-19 15:45:41 (GMT)
committerMathias Gumz <akira@fluxbox.org>2016-06-26 14:35:16 (GMT)
commit1a61881ec34a5f3691df1159f63a4b5afb1f53c4 (patch)
tree8ab844e8790c75a0e9dcc2ea44143dea47649758
parent69b0f0fa97f53f601a250dc1b5a6876f64796a91 (diff)
downloadfluxbox-1a61881ec34a5f3691df1159f63a4b5afb1f53c4.zip
fluxbox-1a61881ec34a5f3691df1159f63a4b5afb1f53c4.tar.bz2
Add FocusProtection features
The apps file gets a new key FocusProtection supporting a comma separated list. * None : regular behavior * Lock : If this window has the focus, no other may claim it * Deny : This window is not allowed to focus itself I addition there's preparation for a follow-up patch to incorporate and substitute the present FocusNewWindow feature: * Gain : Pass focus to new window * Refuse : Do not pass focus to new window rationale: clients stealing the focus sucks badly and while there's an input driven timeout, that only protects actual typing flow, but if eg. vlc proceeds on the playlist, you'll suddenly control vlc instead of your browser (ie. typing ctrl+w doesn't close the tab, but the playlist ...)
-rw-r--r--src/FocusControl.cc7
-rw-r--r--src/Remember.cc65
-rw-r--r--src/Remember.hh2
-rw-r--r--src/Window.cc13
-rw-r--r--src/Window.hh17
5 files changed, 102 insertions, 2 deletions
diff --git a/src/FocusControl.cc b/src/FocusControl.cc
index 3be7937..f59b5ff 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -588,6 +588,13 @@ void FocusControl::setFocusedWindow(WinClient *client) {
588 } 588 }
589 } 589 }
590 590
591 if (client != expectingFocus() && s_focused_window &&
592 ((s_focused_fbwindow->focusProtection() & Focus::Lock) ||
593 (client && client->fbwindow() && (client->fbwindow()->focusProtection() & Focus::Deny)))) {
594 s_focused_window->focus();
595 return;
596 }
597
591 BScreen *old_screen = 598 BScreen *old_screen =
592 FocusControl::focusedWindow() ? 599 FocusControl::focusedWindow() ?
593 &FocusControl::focusedWindow()->screen() : 0; 600 &FocusControl::focusedWindow()->screen() : 0;
diff --git a/src/Remember.cc b/src/Remember.cc
index 6dcd378..43a4d16 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -98,6 +98,7 @@ public:
98 void forgetIconHiddenstate() { iconhiddenstate_remember= false; } 98 void forgetIconHiddenstate() { iconhiddenstate_remember= false; }
99 void forgetStuckstate() { stuckstate_remember = false; } 99 void forgetStuckstate() { stuckstate_remember = false; }
100 void forgetFocusNewWindow() { focusnewwindow_remember = false; } 100 void forgetFocusNewWindow() { focusnewwindow_remember = false; }
101 void forgetFocusProtection() { focusprotection_remember = false; }
101 void forgetJumpworkspace() { jumpworkspace_remember = false; } 102 void forgetJumpworkspace() { jumpworkspace_remember = false; }
102 void forgetLayer() { layer_remember = false; } 103 void forgetLayer() { layer_remember = false; }
103 void forgetSaveOnClose() { save_on_close_remember = false; } 104 void forgetSaveOnClose() { save_on_close_remember = false; }
@@ -140,6 +141,8 @@ public:
140 { stuckstate = state; stuckstate_remember = true; } 141 { stuckstate = state; stuckstate_remember = true; }
141 void rememberFocusNewWindow(bool state) 142 void rememberFocusNewWindow(bool state)
142 { focusnewwindow = state; focusnewwindow_remember = true; } 143 { focusnewwindow = state; focusnewwindow_remember = true; }
144 void rememberFocusProtection(unsigned int protect)
145 { focusprotection = protect; focusprotection_remember = true; }
143 void rememberJumpworkspace(bool state) 146 void rememberJumpworkspace(bool state)
144 { jumpworkspace = state; jumpworkspace_remember = true; } 147 { jumpworkspace = state; jumpworkspace_remember = true; }
145 void rememberLayer(int layernum) 148 void rememberLayer(int layernum)
@@ -191,6 +194,9 @@ public:
191 bool focusnewwindow_remember; 194 bool focusnewwindow_remember;
192 bool focusnewwindow; 195 bool focusnewwindow;
193 196
197 bool focusprotection_remember;
198 unsigned int focusprotection;
199
194 bool focushiddenstate_remember; 200 bool focushiddenstate_remember;
195 bool focushiddenstate; 201 bool focushiddenstate;
196 202
@@ -242,6 +248,7 @@ void Application::reset() {
242 shadedstate_remember = 248 shadedstate_remember =
243 stuckstate_remember = 249 stuckstate_remember =
244 focusnewwindow_remember = 250 focusnewwindow_remember =
251 focusprotection_remember =
245 tabstate_remember = 252 tabstate_remember =
246 workspace_remember = 253 workspace_remember =
247 head_remember = 254 head_remember =
@@ -549,6 +556,26 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) {
549 app.rememberStuckstate(str_label == "yes"); 556 app.rememberStuckstate(str_label == "yes");
550 } else if (str_key == "focusnewwindow") { 557 } else if (str_key == "focusnewwindow") {
551 app.rememberFocusNewWindow(str_label == "yes"); 558 app.rememberFocusNewWindow(str_label == "yes");
559 } else if (str_key == "focusprotection") {
560 Focus::Protection protect = Focus::NoProtection;
561 std::list<std::string> labels;
562 FbTk::StringUtil::stringtok(labels, str_label, ", ");
563 std::list<std::string>::iterator it = labels.begin();
564 for (; it != labels.end(); ++it) {
565 if (*it == "lock")
566 protect = (protect & ~Focus::Deny) | Focus::Lock;
567 else if (*it == "deny")
568 protect = (protect & ~Focus::Lock) | Focus::Deny;
569 else if (*it == "gain")
570 protect = (protect & ~Focus::Refuse) | Focus::Gain;
571 else if (*it == "refuse")
572 protect = (protect & ~Focus::Gain) | Focus::Refuse;
573 else if (*it == "none")
574 protect = Focus::NoProtection;
575 else
576 had_error = 1;
577 }
578 app.rememberFocusProtection(protect);
552 } else if (str_key == "minimized") { 579 } else if (str_key == "minimized") {
553 app.rememberMinimizedstate(str_label == "yes"); 580 app.rememberMinimizedstate(str_label == "yes");
554 } else if (str_key == "maximized") { 581 } else if (str_key == "maximized") {
@@ -1009,6 +1036,31 @@ void Remember::save() {
1009 if (a.focusnewwindow_remember) { 1036 if (a.focusnewwindow_remember) {
1010 apps_file << " [FocusNewWindow]\t{" << ((a.focusnewwindow)?"yes":"no") << "}" << endl; 1037 apps_file << " [FocusNewWindow]\t{" << ((a.focusnewwindow)?"yes":"no") << "}" << endl;
1011 } 1038 }
1039 if (a.focusprotection_remember) {
1040 apps_file << " [FocusProtection]\t{";
1041 if (a.focusprotection == Focus::NoProtection) {
1042 apps_file << "none";
1043 } else {
1044 bool b = false;
1045 if (a.focusprotection & Focus::Gain) {
1046 apps_file << (b?",":"") << "gain";
1047 b = true;
1048 }
1049 if (a.focusprotection & Focus::Refuse) {
1050 apps_file << (b?",":"") << "refuse";
1051 b = true;
1052 }
1053 if (a.focusprotection & Focus::Lock) {
1054 apps_file << (b?",":"") << "lock";
1055 b = true;
1056 }
1057 if (a.focusprotection & Focus::Deny) {
1058 apps_file << (b?",":"") << "deny";
1059 b = true;
1060 }
1061 }
1062 apps_file << "}" << endl;
1063 }
1012 if (a.minimizedstate_remember) { 1064 if (a.minimizedstate_remember) {
1013 apps_file << " [Minimized]\t{" << ((a.minimizedstate)?"yes":"no") << "}" << endl; 1065 apps_file << " [Minimized]\t{" << ((a.minimizedstate)?"yes":"no") << "}" << endl;
1014 } 1066 }
@@ -1083,6 +1135,9 @@ bool Remember::isRemembered(WinClient &winclient, Attribute attrib) {
1083 case REM_FOCUSNEWWINDOW: 1135 case REM_FOCUSNEWWINDOW:
1084 return app->focusnewwindow_remember; 1136 return app->focusnewwindow_remember;
1085 break; 1137 break;
1138 case REM_FOCUSPROTECTION:
1139 return app->focusprotection_remember;
1140 break;
1086 case REM_MINIMIZEDSTATE: 1141 case REM_MINIMIZEDSTATE:
1087 return app->minimizedstate_remember; 1142 return app->minimizedstate_remember;
1088 break; 1143 break;
@@ -1166,6 +1221,9 @@ void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) {
1166 case REM_FOCUSNEWWINDOW: 1221 case REM_FOCUSNEWWINDOW:
1167 app->rememberFocusNewWindow(win->isFocusNew()); 1222 app->rememberFocusNewWindow(win->isFocusNew());
1168 break; 1223 break;
1224 case REM_FOCUSPROTECTION:
1225 app->rememberFocusProtection(win->focusProtection());
1226 break;
1169 case REM_MINIMIZEDSTATE: 1227 case REM_MINIMIZEDSTATE:
1170 app->rememberMinimizedstate(win->isIconic()); 1228 app->rememberMinimizedstate(win->isIconic());
1171 break; 1229 break;
@@ -1229,6 +1287,9 @@ void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
1229 case REM_FOCUSNEWWINDOW: 1287 case REM_FOCUSNEWWINDOW:
1230 app->forgetFocusNewWindow(); 1288 app->forgetFocusNewWindow();
1231 break; 1289 break;
1290 case REM_FOCUSPROTECTION:
1291 app->forgetFocusProtection();
1292 break;
1232 case REM_MINIMIZEDSTATE: 1293 case REM_MINIMIZEDSTATE:
1233 app->forgetMinimizedstate(); 1294 app->forgetMinimizedstate();
1234 break; 1295 break;
@@ -1355,6 +1416,10 @@ void Remember::setupFrame(FluxboxWindow &win) {
1355 if (app->focusnewwindow_remember) 1416 if (app->focusnewwindow_remember)
1356 win.setFocusNew(app->focusnewwindow); 1417 win.setFocusNew(app->focusnewwindow);
1357 1418
1419 if (app->focusprotection_remember) {
1420 win.setFocusProtection(app->focusprotection);
1421 }
1422
1358 if (app->minimizedstate_remember) { 1423 if (app->minimizedstate_remember) {
1359 // if inconsistent... 1424 // if inconsistent...
1360 // this one doesn't actually work, but I can't imagine needing it 1425 // this one doesn't actually work, but I can't imagine needing it
diff --git a/src/Remember.hh b/src/Remember.hh
index a6a980e..59fb1d3 100644
--- a/src/Remember.hh
+++ b/src/Remember.hh
@@ -75,6 +75,7 @@ public:
75 REM_MAXIMIZEDSTATE, 75 REM_MAXIMIZEDSTATE,
76 REM_FULLSCREENSTATE, 76 REM_FULLSCREENSTATE,
77 REM_FOCUSNEWWINDOW, 77 REM_FOCUSNEWWINDOW,
78 REM_FOCUSPROTECTION,
78 REM_LASTATTRIB // not actually used 79 REM_LASTATTRIB // not actually used
79 }; 80 };
80 81
@@ -87,7 +88,6 @@ public:
87 }; 88 };
88 89
89 90
90
91 // a "pattern" to the relevant app 91 // a "pattern" to the relevant app
92 // each app exists ONLY for that pattern. 92 // each app exists ONLY for that pattern.
93 // And we need to keep a list of pairs as we want to keep the 93 // And we need to keep a list of pairs as we want to keep the
diff --git a/src/Window.cc b/src/Window.cc
index ac76aee..929cec8 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -291,6 +291,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client):
291 m_client(&client), 291 m_client(&client),
292 m_toggled_decos(false), 292 m_toggled_decos(false),
293 m_focus_new(BoolAcc(screen().focusControl(), &FocusControl::focusNew)), 293 m_focus_new(BoolAcc(screen().focusControl(), &FocusControl::focusNew)),
294 m_focus_protection(Focus::NoProtection),
294 m_mouse_focus(BoolAcc(screen().focusControl(), &FocusControl::isMouseFocus)), 295 m_mouse_focus(BoolAcc(screen().focusControl(), &FocusControl::isMouseFocus)),
295 m_click_focus(true), 296 m_click_focus(true),
296 m_last_button_x(0), m_last_button_y(0), 297 m_last_button_x(0), m_last_button_y(0),
@@ -563,7 +564,10 @@ void FluxboxWindow::init() {
563 // check if we should prevent this window from gaining focus 564 // check if we should prevent this window from gaining focus
564 m_focused = false; // deiconify sets this 565 m_focused = false; // deiconify sets this
565 if (!Fluxbox::instance()->isStartup() && m_focus_new) { 566 if (!Fluxbox::instance()->isStartup() && m_focus_new) {
567 Focus::Protection fp = m_focus_protection;
568 m_focus_protection &= ~Focus::Deny; // new windows run as "Refuse"
566 m_focused = focusRequestFromClient(*m_client); 569 m_focused = focusRequestFromClient(*m_client);
570 m_focus_protection = fp;
567 if (!m_focused) 571 if (!m_focused)
568 lower(); 572 lower();
569 } 573 }
@@ -2025,7 +2029,10 @@ void FluxboxWindow::mapRequestEvent(XMapRequestEvent &re) {
2025 2029
2026 if (m_focus_new) { 2030 if (m_focus_new) {
2027 m_focused = false; // deiconify sets this 2031 m_focused = false; // deiconify sets this
2032 Focus::Protection fp = m_focus_protection;
2033 m_focus_protection &= ~Focus::Deny; // goes by "Refuse"
2028 m_focused = focusRequestFromClient(*client); 2034 m_focused = focusRequestFromClient(*client);
2035 m_focus_protection = fp;
2029 if (!m_focused) 2036 if (!m_focused)
2030 lower(); 2037 lower();
2031 } 2038 }
@@ -2041,9 +2048,13 @@ bool FluxboxWindow::focusRequestFromClient(WinClient &from) {
2041 2048
2042 FluxboxWindow *cur = FocusControl::focusedFbWindow(); 2049 FluxboxWindow *cur = FocusControl::focusedFbWindow();
2043 WinClient *client = FocusControl::focusedWindow(); 2050 WinClient *client = FocusControl::focusedWindow();
2044 if (cur && getRootTransientFor(&from) != getRootTransientFor(client)) 2051 if ((from.fbwindow() && (from.fbwindow()->focusProtection() & Focus::Deny)) ||
2052 (cur && (cur->focusProtection() & Focus::Lock))) {
2053 ret = false;
2054 } else if (cur && getRootTransientFor(&from) != getRootTransientFor(client)) {
2045 ret = !(cur->isFullscreen() && getOnHead() == cur->getOnHead()) && 2055 ret = !(cur->isFullscreen() && getOnHead() == cur->getOnHead()) &&
2046 !cur->isTyping(); 2056 !cur->isTyping();
2057 }
2047 2058
2048 if (!ret) 2059 if (!ret)
2049 Fluxbox::instance()->attentionHandler().addAttention(from); 2060 Fluxbox::instance()->attentionHandler().addAttention(from);
diff --git a/src/Window.hh b/src/Window.hh
index c04676a..706f8ed 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -56,6 +56,18 @@ class ImageControl;
56class Layer; 56class Layer;
57} 57}
58 58
59namespace Focus {
60 enum {
61 NoProtection = 0,
62 Gain = 1,
63 Refuse = 2,
64 Lock = 4,
65 Deny = 8
66 };
67 typedef unsigned int Protection;
68}
69
70
59/// Creates the window frame and handles any window event for it 71/// Creates the window frame and handles any window event for it
60class FluxboxWindow: public Focusable, 72class FluxboxWindow: public Focusable,
61 public FbTk::EventHandler, 73 public FbTk::EventHandler,
@@ -256,6 +268,8 @@ public:
256 void setIconHidden(bool value); 268 void setIconHidden(bool value);
257 /// sets whether or not the window normally gets focus when mapped 269 /// sets whether or not the window normally gets focus when mapped
258 void setFocusNew(bool value) { m_focus_new = value; } 270 void setFocusNew(bool value) { m_focus_new = value; }
271 /// sets how to protect the focus on or against this window
272 void setFocusProtection(Focus::Protection value) { m_focus_protection = value; }
259 /// sets whether or not the window gets focused with mouse 273 /// sets whether or not the window gets focused with mouse
260 void setMouseFocus(bool value) { m_mouse_focus = value; } 274 void setMouseFocus(bool value) { m_mouse_focus = value; }
261 /// sets whether or not the window gets focused with click 275 /// sets whether or not the window gets focused with click
@@ -384,6 +398,7 @@ public:
384 bool isMoveable() const { return functions.move; } 398 bool isMoveable() const { return functions.move; }
385 bool isStuck() const { return m_state.stuck; } 399 bool isStuck() const { return m_state.stuck; }
386 bool isFocusNew() const { return m_focus_new; } 400 bool isFocusNew() const { return m_focus_new; }
401 Focus::Protection focusProtection() const { return m_focus_protection; }
387 bool hasTitlebar() const { return decorations.titlebar; } 402 bool hasTitlebar() const { return decorations.titlebar; }
388 bool isMoving() const { return moving; } 403 bool isMoving() const { return moving; }
389 bool isResizing() const { return resizing; } 404 bool isResizing() const { return resizing; }
@@ -572,6 +587,8 @@ private:
572 typedef FbTk::ConstObjectAccessor<bool, FocusControl> BoolAcc; 587 typedef FbTk::ConstObjectAccessor<bool, FocusControl> BoolAcc;
573 /// if the window is normally focused when mapped 588 /// if the window is normally focused when mapped
574 FbTk::DefaultValue<bool, BoolAcc> m_focus_new; 589 FbTk::DefaultValue<bool, BoolAcc> m_focus_new;
590 /// special focus permissions
591 Focus::Protection m_focus_protection;
575 /// if the window is focused with EnterNotify 592 /// if the window is focused with EnterNotify
576 FbTk::DefaultValue<bool, BoolAcc> m_mouse_focus; 593 FbTk::DefaultValue<bool, BoolAcc> m_mouse_focus;
577 bool m_click_focus; ///< if the window is focused by clicking 594 bool m_click_focus; ///< if the window is focused by clicking