summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/FocusControl.cc69
-rw-r--r--src/FocusControl.hh16
-rw-r--r--src/Window.cc30
-rw-r--r--src/WorkspaceCmd.cc34
-rw-r--r--src/fluxbox.cc35
5 files changed, 73 insertions, 111 deletions
diff --git a/src/FocusControl.cc b/src/FocusControl.cc
index 5cbf645..f4c8cdf 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -54,7 +54,7 @@ FocusControl::FocusControl(BScreen &screen):
54 m_focus_new(screen.resourceManager(), true, 54 m_focus_new(screen.resourceManager(), true,
55 screen.name()+".focusNewWindows", 55 screen.name()+".focusNewWindows",
56 screen.altName()+".FocusNewWindows"), 56 screen.altName()+".FocusNewWindows"),
57 m_cycling_focus(false), 57 m_cycling_list(0),
58 m_was_iconic(false), 58 m_was_iconic(false),
59 m_cycling_last(0) { 59 m_cycling_last(0) {
60 60
@@ -79,26 +79,25 @@ bool doSkipWindow(const WinClient &winclient, int opts) {
79 ); 79 );
80} 80}
81 81
82void FocusControl::cycleFocus(int opts, bool cycle_reverse) { 82void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) {
83 83
84 FocusedWindows *window_list = (opts & CYCLELINEAR) ? &m_creation_order_list : &m_focused_list; 84 if (!m_cycling_list) {
85 if (!m_cycling_focus) {
86 if (&m_screen == Fluxbox::instance()->watchingScreen()) 85 if (&m_screen == Fluxbox::instance()->watchingScreen())
87 m_cycling_focus = true; 86 // only set this when we're waiting for modifiers
88 m_cycling_window = find(window_list->begin(),window_list->end(),s_focused_window); 87 m_cycling_list = window_list;
89 m_cycling_creation_order = (opts & CYCLELINEAR); 88 m_was_iconic = 0;
90 m_was_iconic = false;
91 m_cycling_last = 0; 89 m_cycling_last = 0;
92 } else if (m_cycling_creation_order ^ (bool)(opts & CYCLELINEAR)) { 90 } else if (m_cycling_list != window_list)
93 m_cycling_creation_order ^= true; 91 m_cycling_list = window_list;
94 m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window); 92
95 } 93 // too many things can go wrong with remembering this
96 // if it is stacked, we want the highest window in the focused list 94 m_cycling_window = find(window_list->begin(),window_list->end(),s_focused_window);
97 // that is on the same workspace 95
98 FocusedWindows::iterator it = m_cycling_window; 96 FocusedWindows::iterator it = m_cycling_window;
99 FocusedWindows::iterator it_begin = window_list->begin(); 97 FocusedWindows::iterator it_begin = window_list->begin();
100 FocusedWindows::iterator it_end = window_list->end(); 98 FocusedWindows::iterator it_end = window_list->end();
101 99
100 // find the next window in the list that works
102 while (true) { 101 while (true) {
103 if (cycle_reverse && it == it_begin) 102 if (cycle_reverse && it == it_begin)
104 it = it_end; 103 it = it_end;
@@ -130,12 +129,18 @@ void FocusControl::cycleFocus(int opts, bool cycle_reverse) {
130 129
131 // set back to orig current Client in that fbwin 130 // set back to orig current Client in that fbwin
132 m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); 131 m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false);
132 if (m_was_iconic == m_cycling_last) {
133 s_reverting = true; // little hack
134 m_cycling_last->fbwindow()->iconify();
135 s_reverting = false;
136 }
133 } 137 }
134 m_cycling_last = &last_client; 138 m_cycling_last = &last_client;
135 if (m_was_iconic) 139 if (fbwin->isIconic())
136 (*m_cycling_window)->fbwindow()->iconify(); 140 m_was_iconic = m_cycling_last;
137 m_was_iconic = fbwin->isIconic(); 141 if (m_cycling_list)
138 fbwin->tempRaise(); 142 // else window will raise itself (if desired) on FocusIn
143 fbwin->tempRaise();
139 } 144 }
140 break; 145 break;
141 } 146 }
@@ -158,7 +163,7 @@ void FocusControl::addFocusFront(WinClient &client) {
158void FocusControl::setFocusBack(FluxboxWindow *fbwin) { 163void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
159 // do nothing if there are no windows open 164 // do nothing if there are no windows open
160 // don't change focus order while cycling 165 // don't change focus order while cycling
161 if (m_focused_list.empty() || isCycling()) 166 if (m_focused_list.empty() || s_reverting)
162 return; 167 return;
163 168
164 FocusedWindows::iterator it = m_focused_list.begin(); 169 FocusedWindows::iterator it = m_focused_list.begin();
@@ -181,28 +186,24 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
181 186
182void FocusControl::stopCyclingFocus() { 187void FocusControl::stopCyclingFocus() {
183 // nothing to do 188 // nothing to do
184 if (!m_cycling_focus) 189 if (m_cycling_list == 0)
185 return; 190 return;
186 191
187 m_cycling_focus = false; 192 FocusedWindows::iterator it_end = m_cycling_list->end();
188 m_cycling_last = 0; 193 m_cycling_last = 0;
194 m_cycling_list = 0;
195
189 // put currently focused window to top 196 // put currently focused window to top
190 // the iterator may be invalid if the window died 197 // the iterator may be invalid if the window died
191 // in which case we'll do a proper revert focus 198 // in which case we'll do a proper revert focus
192 if (m_cycling_creation_order && m_cycling_window != m_creation_order_list.end()) 199 if (m_cycling_window != it_end && (*m_cycling_window)->fbwindow() &&
193 m_cycling_window = find(m_focused_list.begin(),m_focused_list.end(),*m_cycling_window);
194 if (m_cycling_window != m_focused_list.end() &&
195 m_cycling_window != m_creation_order_list.end() &&
196 (*m_cycling_window)->fbwindow() &&
197 (*m_cycling_window)->fbwindow()->isVisible()) { 200 (*m_cycling_window)->fbwindow()->isVisible()) {
198 WinClient *client = *m_cycling_window; 201 WinClient *client = *m_cycling_window;
199 m_focused_list.erase(m_cycling_window); 202 m_focused_list.remove(client);
200 m_focused_list.push_front(client); 203 m_focused_list.push_front(client);
201 client->fbwindow()->raise(); 204 client->fbwindow()->raise();
202 } else { 205 } else
203 revertFocus(m_screen); 206 revertFocus(m_screen);
204 }
205
206} 207}
207 208
208/** 209/**
@@ -254,7 +255,6 @@ void FocusControl::setScreenFocusedWindow(WinClient &win_client) {
254 !Fluxbox::instance()->isStartup()) { 255 !Fluxbox::instance()->isStartup()) {
255 m_focused_list.remove(&win_client); 256 m_focused_list.remove(&win_client);
256 m_focused_list.push_front(&win_client); 257 m_focused_list.push_front(&win_client);
257 m_cycling_window = m_focused_list.begin();
258 } 258 }
259} 259}
260 260
@@ -370,14 +370,14 @@ void FocusControl::removeClient(WinClient &client) {
370 return; 370 return;
371 371
372 WinClient *cyc = 0; 372 WinClient *cyc = 0;
373 if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end()) 373 if (m_cycling_list && m_cycling_window != m_cycling_list->end())
374 cyc = *m_cycling_window; 374 cyc = *m_cycling_window;
375 375
376 m_focused_list.remove(&client); 376 m_focused_list.remove(&client);
377 m_creation_order_list.remove(&client); 377 m_creation_order_list.remove(&client);
378 378
379 if (cyc == &client) { 379 if (cyc == &client) {
380 m_cycling_window = m_creation_order_list.end(); 380 m_cycling_window = m_cycling_list->end();
381 stopCyclingFocus(); 381 stopCyclingFocus();
382 } 382 }
383} 383}
@@ -402,8 +402,7 @@ void FocusControl::shutdown() {
402 * it gets a focusIn 402 * it gets a focusIn
403 */ 403 */
404void FocusControl::revertFocus(BScreen &screen) { 404void FocusControl::revertFocus(BScreen &screen) {
405 405 if (s_reverting)
406 if (screen.focusControl().isCycling())
407 return; 406 return;
408 407
409 FocusControl::s_reverting = true; 408 FocusControl::s_reverting = true;
diff --git a/src/FocusControl.hh b/src/FocusControl.hh
index ee5fe95..ee66b9e 100644
--- a/src/FocusControl.hh
+++ b/src/FocusControl.hh
@@ -68,11 +68,9 @@ public:
68 68
69 explicit FocusControl(BScreen &screen); 69 explicit FocusControl(BScreen &screen);
70 70
71 void prevFocus() { cycleFocus(0, true); } 71 void prevFocus() { cycleFocus(&m_focused_list, 0, true); }
72 void nextFocus() { cycleFocus(0, false); } 72 void nextFocus() { cycleFocus(&m_focused_list, 0, false); }
73 void prevFocus(int options) { cycleFocus(options, true); } 73 void cycleFocus(FocusedWindows *winlist, int options, bool reverse = false);
74 void nextFocus(int options) { cycleFocus(options, false); }
75 void cycleFocus(int options, bool cycle_reverse);
76 74
77 void setScreenFocusedWindow(WinClient &win_client); 75 void setScreenFocusedWindow(WinClient &win_client);
78 void setFocusModel(FocusModel model); 76 void setFocusModel(FocusModel model);
@@ -83,7 +81,7 @@ public:
83 void dirFocus(FluxboxWindow &win, FocusDir dir); 81 void dirFocus(FluxboxWindow &win, FocusDir dir);
84 bool isMouseFocus() const { return focusModel() == MOUSEFOCUS; } 82 bool isMouseFocus() const { return focusModel() == MOUSEFOCUS; }
85 bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; } 83 bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; }
86 bool isCycling() const { return m_cycling_focus; } 84 bool isCycling() const { return m_cycling_list != 0; }
87 void addFocusBack(WinClient &client); 85 void addFocusBack(WinClient &client);
88 void addFocusFront(WinClient &client); 86 void addFocusFront(WinClient &client);
89 void setFocusBack(FluxboxWindow *fbwin); 87 void setFocusBack(FluxboxWindow *fbwin);
@@ -120,10 +118,10 @@ private:
120 // Screen global so it works for sticky windows too. 118 // Screen global so it works for sticky windows too.
121 FocusedWindows m_focused_list; 119 FocusedWindows m_focused_list;
122 FocusedWindows m_creation_order_list; 120 FocusedWindows m_creation_order_list;
121
123 FocusedWindows::iterator m_cycling_window; 122 FocusedWindows::iterator m_cycling_window;
124 bool m_cycling_focus; 123 FocusedWindows *m_cycling_list;
125 bool m_cycling_creation_order; 124 WinClient *m_was_iconic;
126 bool m_was_iconic;
127 WinClient *m_cycling_last; 125 WinClient *m_cycling_last;
128 126
129 static WinClient *s_focused_window; 127 static WinClient *s_focused_window;
diff --git a/src/Window.cc b/src/Window.cc
index 27992f0..4e02bfe 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -777,36 +777,14 @@ void FluxboxWindow::nextClient() {
777 if (numClients() <= 1) 777 if (numClients() <= 1)
778 return; 778 return;
779 779
780 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client); 780 screen().focusControl().cycleFocus(&m_clientlist, 0);
781 WinClient *client = 0;
782 if (it == m_clientlist.end()) {
783 client = m_clientlist.front();
784 } else {
785 it++;
786 if (it == m_clientlist.end())
787 client = m_clientlist.front();
788 else
789 client = *it;
790 }
791 setCurrentClient(*client, true);
792} 781}
793 782
794void FluxboxWindow::prevClient() { 783void FluxboxWindow::prevClient() {
795 if (numClients() <= 1) 784 if (numClients() <= 1)
796 return; 785 return;
797 786
798 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client); 787 screen().focusControl().cycleFocus(&m_clientlist, 0, true);
799 WinClient *client = 0;
800 if (it == m_clientlist.end()) {
801 client = m_clientlist.front();
802 } else {
803 if (it == m_clientlist.begin())
804 client = m_clientlist.back();
805 else
806 client = *(--it);
807 }
808
809 setCurrentClient(*client, true);
810} 788}
811 789
812 790
@@ -3909,8 +3887,6 @@ void FluxboxWindow::setupWindow() {
3909 // sets up our window 3887 // sets up our window
3910 // we allow both to be done at once to share the commands 3888 // we allow both to be done at once to share the commands
3911 3889
3912 WinButtonTheme &winbutton_theme = screen().winButtonTheme();
3913
3914 using namespace FbTk; 3890 using namespace FbTk;
3915 typedef RefCount<Command> CommandRef; 3891 typedef RefCount<Command> CommandRef;
3916 typedef SimpleCommand<FluxboxWindow> WindowCmd; 3892 typedef SimpleCommand<FluxboxWindow> WindowCmd;
@@ -4024,7 +4000,7 @@ void FluxboxWindow::updateButtons() {
4024 if (new_size != m_titlebar_buttons[i].size() || need_update) 4000 if (new_size != m_titlebar_buttons[i].size() || need_update)
4025 need_update = true; 4001 need_update = true;
4026 else { 4002 else {
4027 for (int j=0; j < new_size && !need_update; j++) { 4003 for (size_t j=0; j < new_size && !need_update; j++) {
4028 if ((*(*titlebar_side[i]))[j] != m_titlebar_buttons[i][j]) 4004 if ((*(*titlebar_side[i]))[j] != m_titlebar_buttons[i][j])
4029 need_update = true; 4005 need_update = true;
4030 } 4006 }
diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc
index 414f942..7d384aa 100644
--- a/src/WorkspaceCmd.cc
+++ b/src/WorkspaceCmd.cc
@@ -53,14 +53,19 @@ void NextWindowCmd::execute() {
53 } else if (ev.type == ButtonPress) { 53 } else if (ev.type == ButtonPress) {
54 mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); 54 mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
55 } 55 }
56 int options = m_option;
56 if (mods == 0) // can't stacked cycle unless there is a mod to grab 57 if (mods == 0) // can't stacked cycle unless there is a mod to grab
57 screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR); 58 options |= FocusControl::CYCLELINEAR;
58 else { 59 else
59 // if stacked cycling, then set a watch for 60 // set a watch for the release of exactly these modifiers
60 // the release of exactly these modifiers
61 fb->watchKeyRelease(*screen, mods); 61 fb->watchKeyRelease(*screen, mods);
62 screen->focusControl().nextFocus(m_option); 62
63 } 63 FocusControl::FocusedWindows *win_list =
64 (options & FocusControl::CYCLELINEAR) ?
65 &screen->focusControl().creationOrderList() :
66 &screen->focusControl().focusedOrderList();
67
68 screen->focusControl().cycleFocus(win_list, m_option);
64 } 69 }
65} 70}
66 71
@@ -76,14 +81,19 @@ void PrevWindowCmd::execute() {
76 } else if (ev.type == ButtonPress) { 81 } else if (ev.type == ButtonPress) {
77 mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); 82 mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
78 } 83 }
84 int options = m_option;
79 if (mods == 0) // can't stacked cycle unless there is a mod to grab 85 if (mods == 0) // can't stacked cycle unless there is a mod to grab
80 screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR); 86 options |= FocusControl::CYCLELINEAR;
81 else { 87 else
82 // if stacked cycling, then set a watch for 88 // set a watch for the release of exactly these modifiers
83 // the release of exactly these modifiers
84 fb->watchKeyRelease(*screen, mods); 89 fb->watchKeyRelease(*screen, mods);
85 screen->focusControl().prevFocus(m_option); 90
86 } 91 FocusControl::FocusedWindows *win_list =
92 (options & FocusControl::CYCLELINEAR) ?
93 &screen->focusControl().creationOrderList() :
94 &screen->focusControl().focusedOrderList();
95
96 screen->focusControl().cycleFocus(win_list, m_option, true);
87 } 97 }
88} 98}
89 99
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 468e723..89bd0d5 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -970,19 +970,7 @@ void Fluxbox::handleButtonEvent(XButtonEvent &be) {
970 if (be.button == 1 && !screen->isRootColormapInstalled()) 970 if (be.button == 1 && !screen->isRootColormapInstalled())
971 screen->imageControl().installRootColormap(); 971 screen->imageControl().installRootColormap();
972 972
973 // see if we need to keep watching for key releases 973 m_key->doAction(be.type, be.state, be.button);
974 BScreen *old_watching_screen = m_watching_screen;
975 m_watching_screen = 0;
976 if (!m_key->doAction(be.type, be.state, be.button))
977 // no command run, so could still be cycling
978 m_watching_screen = old_watching_screen;
979 else if (old_watching_screen &&
980 m_watching_screen != old_watching_screen) {
981 // no longer need to watch old screen, so stop cycling
982 old_watching_screen->notifyReleasedKeys();
983 if (!m_watching_screen)
984 XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
985 }
986} 974}
987 975
988void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) { 976void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) {
@@ -1113,21 +1101,9 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
1113 if (keyScreen() == 0 || mouseScreen() == 0) 1101 if (keyScreen() == 0 || mouseScreen() == 0)
1114 return; 1102 return;
1115 1103
1116 BScreen *old_watching_screen = m_watching_screen;
1117
1118 switch (ke.type) { 1104 switch (ke.type) {
1119 case KeyPress: 1105 case KeyPress:
1120 // see if we need to keep watching for key releases 1106 m_key->doAction(ke.type, ke.state, ke.keycode);
1121 m_watching_screen = 0;
1122 if (!m_key->doAction(ke.type, ke.state, ke.keycode))
1123 // no command run, so could still be cycling
1124 m_watching_screen = old_watching_screen;
1125 else if (old_watching_screen &&
1126 m_watching_screen != old_watching_screen) {
1127 old_watching_screen->notifyReleasedKeys();
1128 if (!m_watching_screen)
1129 XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
1130 }
1131 break; 1107 break;
1132 case KeyRelease: { 1108 case KeyRelease: {
1133 // we ignore most key releases unless we need to use 1109 // we ignore most key releases unless we need to use
@@ -1841,12 +1817,15 @@ void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) {
1841 cerr<<"WARNING: attempt to grab without modifiers!"<<endl; 1817 cerr<<"WARNING: attempt to grab without modifiers!"<<endl;
1842 return; 1818 return;
1843 } 1819 }
1820 // just make sure we are saving the mods with any other flags (xkb)
1821 m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
1822
1823 if (m_watching_screen == &screen)
1824 return;
1844 if (m_watching_screen) 1825 if (m_watching_screen)
1845 m_watching_screen->focusControl().stopCyclingFocus(); 1826 m_watching_screen->focusControl().stopCyclingFocus();
1846 m_watching_screen = &screen; 1827 m_watching_screen = &screen;
1847 1828
1848 // just make sure we are saving the mods with any other flags (xkb)
1849 m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
1850 // TODO: it's possible (and happens to me sometimes) for the mods to be 1829 // TODO: it's possible (and happens to me sometimes) for the mods to be
1851 // released before we grab the keyboard -- not sure of a good way to fix it 1830 // released before we grab the keyboard -- not sure of a good way to fix it
1852 XGrabKeyboard(FbTk::App::instance()->display(), 1831 XGrabKeyboard(FbTk::App::instance()->display(),