diff options
author | markt <markt> | 2007-03-21 22:10:22 (GMT) |
---|---|---|
committer | markt <markt> | 2007-03-21 22:10:22 (GMT) |
commit | 53fff0d24b996f01d7426e44420c158500a4d311 (patch) | |
tree | 3bee2182e4458e89dba2732594fbc2f71add1331 | |
parent | 51bcee666516ffdbe205b0e74ca209f82fcb1f31 (diff) | |
download | fluxbox-53fff0d24b996f01d7426e44420c158500a4d311.zip fluxbox-53fff0d24b996f01d7426e44420c158500a4d311.tar.bz2 |
added TypeAheadFocus command
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | src/FbCommandFactory.cc | 3 | ||||
-rw-r--r-- | src/Screen.cc | 53 | ||||
-rw-r--r-- | src/Screen.hh | 6 | ||||
-rw-r--r-- | src/WinClient.hh | 5 | ||||
-rw-r--r-- | src/WorkspaceCmd.cc | 14 | ||||
-rw-r--r-- | src/WorkspaceCmd.hh | 8 |
7 files changed, 91 insertions, 5 deletions
@@ -1,5 +1,12 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0rc3: | 2 | Changes for 1.0rc3: |
3 | *07/03/21: | ||
4 | * Added new command TypeAheadFocus (Mark) | ||
5 | - syntax is the same as for NextWindow; when you run the command, you can | ||
6 | start typing the title of the window, and it will gain focus; pressing | ||
7 | tab will cycle through all matching entries using the options specified; | ||
8 | when you've found the window you want, just press return or escape | ||
9 | WinClient.hh Screen.cc/hh FbCommandFactory.cc WorkspaceCmd.cc/hh | ||
3 | *07/03/20: | 10 | *07/03/20: |
4 | * Updated doc/asciidoc/fluxbox.txt (Mathias) | 11 | * Updated doc/asciidoc/fluxbox.txt (Mathias) |
5 | *07/03/19: | 12 | *07/03/19: |
diff --git a/src/FbCommandFactory.cc b/src/FbCommandFactory.cc index c02365a..bd20c39 100644 --- a/src/FbCommandFactory.cc +++ b/src/FbCommandFactory.cc | |||
@@ -145,6 +145,7 @@ FbCommandFactory::FbCommandFactory() { | |||
145 | "taketoprevworkspace", | 145 | "taketoprevworkspace", |
146 | "togglecmd", | 146 | "togglecmd", |
147 | "toggledecor", | 147 | "toggledecor", |
148 | "typeaheadfocus", | ||
148 | "windowmenu", | 149 | "windowmenu", |
149 | "workspace", | 150 | "workspace", |
150 | /* NOTE: The following are DEPRECATED and subject to removal */ | 151 | /* NOTE: The following are DEPRECATED and subject to removal */ |
@@ -419,6 +420,8 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, | |||
419 | return new NextWindowCmd(atoi(arguments.c_str())); | 420 | return new NextWindowCmd(atoi(arguments.c_str())); |
420 | else if (command == "prevwindow") | 421 | else if (command == "prevwindow") |
421 | return new PrevWindowCmd(atoi(arguments.c_str())); | 422 | return new PrevWindowCmd(atoi(arguments.c_str())); |
423 | else if (command == "typeaheadfocus") | ||
424 | return new TypeAheadFocusCmd(atoi(arguments.c_str())); | ||
422 | else if (command == "focusup") | 425 | else if (command == "focusup") |
423 | return new DirFocusCmd(FocusControl::FOCUSUP); | 426 | return new DirFocusCmd(FocusControl::FOCUSUP); |
424 | else if (command == "focusdown") | 427 | else if (command == "focusdown") |
diff --git a/src/Screen.cc b/src/Screen.cc index 987bbd0..4bcc988 100644 --- a/src/Screen.cc +++ b/src/Screen.cc | |||
@@ -365,7 +365,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm, | |||
365 | m_altname(altscreenname), | 365 | m_altname(altscreenname), |
366 | m_focus_control(new FocusControl(*this)), | 366 | m_focus_control(new FocusControl(*this)), |
367 | m_placement_strategy(new ScreenPlacement(*this)), | 367 | m_placement_strategy(new ScreenPlacement(*this)), |
368 | m_cycling(false), | 368 | m_cycling(false), m_typing_ahead(false), m_cycle_opts(0), |
369 | m_xinerama_headinfo(0), | 369 | m_xinerama_headinfo(0), |
370 | m_restart(false), | 370 | m_restart(false), |
371 | m_shutdown(false) { | 371 | m_shutdown(false) { |
@@ -788,7 +788,43 @@ void BScreen::update(FbTk::Subject *subj) { | |||
788 | } | 788 | } |
789 | 789 | ||
790 | void BScreen::keyPressEvent(XKeyEvent &ke) { | 790 | void BScreen::keyPressEvent(XKeyEvent &ke) { |
791 | Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode); | 791 | if (!m_typing_ahead) { |
792 | Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode); | ||
793 | return; | ||
794 | } | ||
795 | |||
796 | KeySym ks; | ||
797 | char keychar[1]; | ||
798 | XLookupString(&ke, keychar, 1, &ks, 0); | ||
799 | // a modifier key by itself doesn't do anything | ||
800 | if (IsModifierKey(ks)) | ||
801 | return; | ||
802 | |||
803 | switch (ks) { | ||
804 | case XK_Escape: | ||
805 | case XK_KP_Enter: | ||
806 | case XK_Return: | ||
807 | m_type_ahead.reset(); | ||
808 | FbTk::EventManager::instance()->ungrabKeyboard(); | ||
809 | break; | ||
810 | case XK_BackSpace: | ||
811 | m_type_ahead.putBackSpace(); | ||
812 | m_matches = m_type_ahead.matched(); | ||
813 | break; | ||
814 | case XK_Tab: | ||
815 | case XK_ISO_Left_Tab: | ||
816 | m_type_ahead.seek(); | ||
817 | focusControl().cycleFocus(&m_matches, m_cycle_opts, (bool)(ke.state & ShiftMask)); | ||
818 | break; | ||
819 | default: | ||
820 | m_matches = m_type_ahead.putCharacter(keychar[0]); | ||
821 | // if focused win doesn't match new search string, find the next one | ||
822 | if (!m_matches.empty() && | ||
823 | std::find(m_matches.begin(), m_matches.end(), | ||
824 | FocusControl::focusedWindow()) == m_matches.end()) | ||
825 | focusControl().cycleFocus(&m_matches, m_cycle_opts); | ||
826 | break; | ||
827 | } | ||
792 | } | 828 | } |
793 | 829 | ||
794 | void BScreen::keyReleaseEvent(XKeyEvent &ke) { | 830 | void BScreen::keyReleaseEvent(XKeyEvent &ke) { |
@@ -812,9 +848,20 @@ void BScreen::buttonPressEvent(XButtonEvent &be) { | |||
812 | 848 | ||
813 | void BScreen::notifyUngrabKeyboard() { | 849 | void BScreen::notifyUngrabKeyboard() { |
814 | m_cycling = false; | 850 | m_cycling = false; |
851 | m_typing_ahead = false; | ||
852 | m_type_ahead.reset(); | ||
815 | focusControl().stopCyclingFocus(); | 853 | focusControl().stopCyclingFocus(); |
816 | } | 854 | } |
817 | 855 | ||
856 | void BScreen::startTypeAheadFocus(std::list<WinClient *> &winlist, int opts) { | ||
857 | m_type_ahead.init(winlist); | ||
858 | FbTk::EventManager *evm = FbTk::EventManager::instance(); | ||
859 | if (!m_typing_ahead && !m_cycling) | ||
860 | evm->grabKeyboard(*this, rootWindow().window()); | ||
861 | m_cycle_opts = opts; | ||
862 | m_typing_ahead = true; | ||
863 | } | ||
864 | |||
818 | void BScreen::cycleFocus(int options, bool reverse) { | 865 | void BScreen::cycleFocus(int options, bool reverse) { |
819 | // get modifiers from event that causes this for focus order cycling | 866 | // get modifiers from event that causes this for focus order cycling |
820 | XEvent ev = Fluxbox::instance()->lastEvent(); | 867 | XEvent ev = Fluxbox::instance()->lastEvent(); |
@@ -824,7 +871,7 @@ void BScreen::cycleFocus(int options, bool reverse) { | |||
824 | else if (ev.type == ButtonPress) | 871 | else if (ev.type == ButtonPress) |
825 | mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); | 872 | mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); |
826 | 873 | ||
827 | if (!m_cycling && mods) { | 874 | if (!m_cycling && !m_typing_ahead && mods) { |
828 | m_cycling = true; | 875 | m_cycling = true; |
829 | FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window()); | 876 | FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window()); |
830 | } | 877 | } |
diff --git a/src/Screen.hh b/src/Screen.hh index bf03ac6..c2e493b 100644 --- a/src/Screen.hh +++ b/src/Screen.hh | |||
@@ -217,6 +217,7 @@ public: | |||
217 | void buttonPressEvent(XButtonEvent &be); | 217 | void buttonPressEvent(XButtonEvent &be); |
218 | void notifyUngrabKeyboard(); | 218 | void notifyUngrabKeyboard(); |
219 | 219 | ||
220 | void startTypeAheadFocus(std::list<WinClient *> &winlist, int opts); | ||
220 | void cycleFocus(int opts, bool reverse); | 221 | void cycleFocus(int opts, bool reverse); |
221 | 222 | ||
222 | FbTk::Menu *createMenu(const std::string &label); | 223 | FbTk::Menu *createMenu(const std::string &label); |
@@ -485,7 +486,10 @@ private: | |||
485 | typedef std::map<Window, WinClient *> Groupables; | 486 | typedef std::map<Window, WinClient *> Groupables; |
486 | Groupables m_expecting_groups; | 487 | Groupables m_expecting_groups; |
487 | 488 | ||
488 | bool m_cycling; | 489 | bool m_cycling, m_typing_ahead; |
490 | int m_cycle_opts; | ||
491 | FbTk::TypeAhead<std::list<WinClient *>, WinClient *> m_type_ahead; | ||
492 | std::list<WinClient *> m_matches; | ||
489 | 493 | ||
490 | // Xinerama related private data | 494 | // Xinerama related private data |
491 | bool m_xinerama_avail; | 495 | bool m_xinerama_avail; |
diff --git a/src/WinClient.hh b/src/WinClient.hh index 0082bb0..7d2c734 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "Subject.hh" | 29 | #include "Subject.hh" |
30 | #include "FbWindow.hh" | 30 | #include "FbWindow.hh" |
31 | #include "FbTk/FbString.hh" | 31 | #include "FbTk/FbString.hh" |
32 | #include "FbTk/ITypeAheadable.hh" | ||
32 | 33 | ||
33 | #include <X11/Xutil.h> | 34 | #include <X11/Xutil.h> |
34 | 35 | ||
@@ -36,7 +37,8 @@ class BScreen; | |||
36 | class Strut; | 37 | class Strut; |
37 | 38 | ||
38 | /// Holds client window info | 39 | /// Holds client window info |
39 | class WinClient: public Focusable, public FbTk::FbWindow { | 40 | class WinClient: public Focusable, public FbTk::ITypeAheadable, |
41 | public FbTk::FbWindow { | ||
40 | public: | 42 | public: |
41 | typedef std::list<WinClient *> TransientList; | 43 | typedef std::list<WinClient *> TransientList; |
42 | // this structure only contains 3 elements... the Motif 2.0 structure contains | 44 | // this structure only contains 3 elements... the Motif 2.0 structure contains |
@@ -143,6 +145,7 @@ public: | |||
143 | inline unsigned int maxWidth() const { return max_width; } | 145 | inline unsigned int maxWidth() const { return max_width; } |
144 | inline unsigned int maxHeight() const { return max_height; } | 146 | inline unsigned int maxHeight() const { return max_height; } |
145 | 147 | ||
148 | const std::string &iTypeString() const { return m_title; } | ||
146 | 149 | ||
147 | static const int PropBlackboxHintsElements = 5; | 150 | static const int PropBlackboxHintsElements = 5; |
148 | static const int PropMwmHintsElements = 3; | 151 | static const int PropMwmHintsElements = 3; |
diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 0cbf5b9..f92418f 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc | |||
@@ -53,6 +53,20 @@ void PrevWindowCmd::execute() { | |||
53 | screen->cycleFocus(m_option, true); | 53 | screen->cycleFocus(m_option, true); |
54 | } | 54 | } |
55 | 55 | ||
56 | void TypeAheadFocusCmd::execute() { | ||
57 | Fluxbox *fb = Fluxbox::instance(); | ||
58 | BScreen *screen = fb->keyScreen(); | ||
59 | if (screen != 0) { | ||
60 | int options = m_option; | ||
61 | FocusControl::FocusedWindows *win_list = | ||
62 | (options & FocusControl::CYCLELINEAR) ? | ||
63 | &screen->focusControl().creationOrderList() : | ||
64 | &screen->focusControl().focusedOrderList(); | ||
65 | |||
66 | screen->startTypeAheadFocus(*win_list, m_option); | ||
67 | } | ||
68 | } | ||
69 | |||
56 | void DirFocusCmd::execute() { | 70 | void DirFocusCmd::execute() { |
57 | BScreen *screen = Fluxbox::instance()->keyScreen(); | 71 | BScreen *screen = Fluxbox::instance()->keyScreen(); |
58 | if (screen == 0) | 72 | if (screen == 0) |
diff --git a/src/WorkspaceCmd.hh b/src/WorkspaceCmd.hh index 7d8d9e6..d0a6713 100644 --- a/src/WorkspaceCmd.hh +++ b/src/WorkspaceCmd.hh | |||
@@ -45,6 +45,14 @@ private: | |||
45 | const int m_option; | 45 | const int m_option; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | class TypeAheadFocusCmd: public FbTk::Command { | ||
49 | public: | ||
50 | explicit TypeAheadFocusCmd(int option): m_option(option) { } | ||
51 | void execute(); | ||
52 | private: | ||
53 | const int m_option; | ||
54 | }; | ||
55 | |||
48 | class DirFocusCmd: public FbTk::Command { | 56 | class DirFocusCmd: public FbTk::Command { |
49 | public: | 57 | public: |
50 | explicit DirFocusCmd(const FocusControl::FocusDir dir): m_dir(dir) { } | 58 | explicit DirFocusCmd(const FocusControl::FocusDir dir): m_dir(dir) { } |