Changeset 193

Show
Ignore:
Timestamp:
07/14/2007 02:38:13 AM (18 months ago)
Author:
mwm
Message:

keys.py: Add allmap to map all printable latin1 keys to a single method.

input.py: Replace initial value hack with history mechanism (mostly)
from Mike O'Connor <stew@…>, and have it use keys.allmap. Also
fix bug in focus loss when menu entries cause a window to open.

menu.py: take advantage of allmap, and add new menuhandler
MenuCharSelectHandler? that selects a menu entry when you hit its key,
as opposed to just going to it. Also some tweaks for xinerama systems.

pane_utilies.py: Make menus work reasonably with more than 26 items,
most notably handling upper-case characters now. Allow the codemenu
class to be invoked without labels, in which case it will construct
them from it's own methods. Add view_menu, which is the view part of
an MVC pattern for menus. See the new xmlcontrol.py for an example of
a corresponding controller object. Remove the editHandler argument to
websearch - we need to use the window arguments edithandler(!). Fix
bug in splitpane where it was using an undefined variable.

examples/plpwm: take advantage of all those nice new tools to
reogranize the key controls, and move the menu configuration into an
external xml config file.

Location:
trunk
Files:
1 added
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/examples/plpwm.py

    r189 r193  
    11#!/usr/bin/env python 
    2 # $Id: plpwm.py,v 1.42 2006-09-15 06:06:26 mwm Exp $ 
     2# $Id: plpwm.py,v 1.43 2007-07-14 07:38:12 mwm Exp $ 
    33# 
    44# plpwm.py -- Example PLWM window manager configuration with panes. 
     
    3030###END SETUP PATH 
    3131 
     32from time import sleep 
     33     
    3234from Xlib import X, XK 
    3335 
     
    3739from plwm.pane_utilities import appmenu, codemenu, windowmenu, panesmenu, \ 
    3840     runcommand, splitpane, numberpane, pullwindow, gotowindow, websearch, \ 
    39      split_pane, getapp 
    40  
    41  
    42 class MyMenuHandler(menu.MenuCharHandler): 
     41     split_pane, getapp, view_menu 
     42 
     43from xmlcontrol import XML_controller, load_menus 
     44 
     45class MyMenuHandler(menu.MenuCharSelecter): 
    4346    Any_Escape = C_g = menu.MenuKeyHandler._abort 
    4447    Any_Return = menu.MenuKeyHandler._do 
     
    5053    Any_Escape = C_g = input.InputKeyHandler._abort 
    5154    Any_Return = input.InputKeyHandler._done 
    52     Any_BackSpace = C_h = input.InputKeyHandler._delback 
     55    Any_Delete = Any_BackSpace = C_h = input.InputKeyHandler._delback 
    5356    C_d = input.InputKeyHandler._delforw 
    5457    C_b = input.InputKeyHandler._back 
     
    5861    C_e = input.InputKeyHandler._end 
    5962    C_y = input.InputKeyHandler._paste 
     63    c_p = input.InputKeyHandler._history_up 
     64    c_n = input.InputKeyHandler._history_down 
    6065 
    6166 
     
    96101    client_class = MyClient 
    97102    screen_class = MyScreen 
    98     panes_maxsize_gravity = X.NorthGravity 
     103    panes_maxsize_gravity = X.NorthWestGravity 
    99104 
    100105 
     
    113118    "The pane control keys." 
    114119 
     120    menu_file = os.path.expanduser('~/.plpwmrc.xml') 
     121 
     122    def __init__(my, obj): 
     123        keys.KeyHandler.__init__(my, obj) 
     124        my.menus = load_menus(my.menu_file) 
     125 
    115126    # Commands for navigating and manipulating panes 
    116127    def C_0(my, event): 
     
    121132    C_1 = C_2 = C_3 = C_4 = C_5 = C_6 = C_7 = C_8 = C_9 = C_0 
    122133 
    123     def M4_Tab(my, event): my.wm.panes_next() 
    124     def S_M4_Tab(my, event): my.wm.panes_prev() 
    125  
    126     def M4_0(my, event): 
     134    def M1_Tab(my, event): my.wm.panes_next() 
     135    def S_M1_Tab(my, event): my.wm.panes_prev() 
     136 
     137    def M1_0(my, event): 
    127138        pane = my.wm.panes_list[my.wm.panes_current] 
    128139        splitpane(pane, pane.horizontal_split, paneWindow) 
    129140 
    130     def S_M4_0(my, event): 
     141    def S_M1_0(my, event): 
    131142        pane = my.wm.panes_list[my.wm.panes_current] 
    132143        splitpane(pane, pane.vertical_split, paneWindow) 
    133144 
    134     def M4_1(my, event): 
     145    def M1_1(my, event): 
    135146        my.wm.panes_list[my.wm.panes_current].maximize() 
    136147 
    137     def M4_2(my, event): 
     148    def M1_2(my, event): 
    138149        split_pane(my.wm.display.keycode_to_keysym(event.detail, 0) - XK.XK_0, 
    139150                   my.wm.panes_list[my.wm.panes_current].horizontal_split) 
    140151 
    141     M4_3 = M4_4 = M4_5 = M4_6 = M4_7 = M4_8 = M4_9 = M4_2 
    142  
    143     def S_M4_2(my, event): 
     152    M1_3 = M1_4 = M1_5 = M1_6 = M1_7 = M1_8 = M1_9 = M1_2 
     153 
     154    def S_M1_2(my, event): 
    144155        split_pane(my.wm.display.keycode_to_keysym(event.detail, 0) - XK.XK_0, 
    145156                   my.wm.panes_list[my.wm.panes_current].vertical_split) 
    146157 
    147     S_M4_3 = S_M4_4 = S_M4_5 = S_M4_6 = S_M4_7 = S_M4_8 = S_M4_9 = S_M4_2 
     158    S_M1_3 = S_M1_4 = S_M1_5 = S_M1_6 = S_M1_7 = S_M1_8 = S_M1_9 = S_M1_2 
    148159  
    149     # Keystrokes for launching applications 
    150     def M4_exclam(my, event): 
     160    def M1_exclam(my, event): 
    151161        runcommand(my.wm.panes_list[my.wm.panes_current], paneWindow) 
    152162 
    153     def M4_b(my, event): 
    154         getapp(my.wm.panes_list[my.wm.panes_current], "w3m") 
    155  
    156     def M4_B(my, event): 
    157         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    158                   "Amazon", paneWindow, 
    159                   'http://www.amazon.com/exec/obidos/search-handle-url/index=blended&field-keywords=%s') 
    160  
    161     def M4_c(my, event): 
    162         getapp(my.wm.panes_list[my.wm.panes_current], 'Sunbird', 'sunbird') 
    163  
    164     def M4_C(my, event): 
    165         getapp(my.wm.panes_list[my.wm.panes_current], "xclipboard") 
    166  
    167     def M4_d(my, event): 
    168         getapp(my.wm.panes_list[my.wm.panes_current], 'Dillo', 'dillo') 
    169  
    170     def M4_D(my, event): 
    171         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    172                   "Webster Dictionary", paneWindow, 
    173                   "http://www.webster.com/cgi-bin/dictionary?book=Dictionary&va=%s") 
    174  
    175     def M4_e(my, event): 
    176         my.wm.panes_goto(0)     # always run emacs in pane 0. 
    177         getapp(my.wm.panes_list[my.wm.panes_current], "emacs", "xemacs") 
    178  
    179     def M4_f(my, event): 
    180         # Damn Firefox doesn't set the title properly when running tabbed, 
    181         # just uses "firefox-bin". So we try both cases. 
    182         getapp(my.wm.panes_list[my.wm.panes_current], "[fF]irefox", "firefox") 
    183  
    184     def M4_g(my, event): 
    185         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    186                   "Google", paneWindow, 
    187                   'http://www.google.com/search?q=%s&hl=en&safe=off') 
    188  
    189     def M4_G(my, event): 
    190         getapp(my.wm.panes_list[my.wm.panes_current], 
    191                "Accounts", "gnucash") 
    192  
    193     def M4_j(my, event): 
    194         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    195                   "Jargon file", paneWindow, 
    196                   "http://www.google.com/search?as_q=%s&as_sitesearch=www.catb.org&btnG=Google+Search") 
    197  
    198     def M4_i(my, event): 
    199         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    200                   "IMDB", paneWindow, 
    201                   "http://www.imdb.com/find?tt=on;nm=on;mx=20;q=%s") 
    202  
    203     def M4_I(my, event): 
    204         def dillo(url): 
    205             assert "'" not in url 
    206             my.wm.system("dillo '%s' &" % url) 
    207  
    208         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    209                   "Google Images", paneWindow, 
    210                   'http://images.google.com/images?q=%s&ie=ISO-8859-1&oe=ISO-8859-1&imgsz=xxlarge&safe=off', 
    211                   dillo) 
    212  
    213     def M4_l(my, event): 
    214         getapp(my.wm.panes_list[my.wm.panes_current], 'LyX', 'lyx') 
    215  
    216     def M4_M(my, event): 
    217         getapp(my.wm.panes_list[my.wm.panes_current], 'Mozilla[^ ]', 'mozilla') 
    218  
    219     def M4_o(my, event): 
    220         getapp(my.wm.panes_list[my.wm.panes_current], 'OpenOffice.org', 
    221                'openoffice.org') 
    222     M4_n = M4_o         # Mac compatability (Neooffice vs. Opera) 
    223  
    224     def M4_p(my, event): 
    225         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    226                   "Python Cookbook", paneWindow, 
    227                   "http://aspn.activestate.com/ASPN/search?query=%s&section=PYTHONCKBK&type=Subsection&x=13&y=3") 
    228  
    229     def M4_P(my, event): 
    230         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    231                   "Python Documentation", paneWindow, 
    232                   'http://starship.python.net/crew/theller/pyhelp.cgi?keyword=%s&version=current') 
    233  
    234     M4_S = M4_c         # Sunbird, to match the Mac  
    235  
    236     def M4_t(my, event): 
    237         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    238                   "TV Tome Search", paneWindow, 
    239                   "http://www.tv.com/search.php?type=11&stype=all&qs=%s&x=0&y=0") 
    240  
    241     def M4_T(my, event): 
    242         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    243                   "Webster Thesaurus", paneWindow, 
    244                   "http://www.webster.com/cgi-bin/thesaurus?book=Thesaurus&va=%s") 
    245  
    246     def M4_w(my, event): 
    247         websearch(my.wm.panes_list[my.wm.panes_current], MyEditHandler, 
    248                   "Wikipedia Dictionary", paneWindow, 
    249                   "http://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go") 
    250  
    251     # Keystrokes for window manager operations 
    252     def M4_equal(my, event): 
     163    def M1_equal(my, event): 
    253164        numberpane(my.wm.panes_list[my.wm.panes_current], paneWindow) 
    254165 
    255     def M4_quoteright(my, event): 
     166    def M1_minus(my, event): 
     167        """Close all the internal windows. Untested""" 
     168 
     169        for s in my.wm.screens: 
     170            for w in s.windows: 
     171                if my.wm.is_internal_window(w): 
     172                    w.destroy() 
     173 
     174    def M1_quoteright(my, event): 
    256175        pullwindow(my.wm.panes_list[my.wm.panes_current], paneWindow) 
    257176 
    258     def M4_quotedbl(my, event): 
     177    def M1_quotedbl(my, event): 
    259178        gotowindow(my.wm.panes_list[my.wm.panes_current], screenWindow) 
    260179 
    261     def M4_space(my, event): 
     180    def M1_space(my, event): 
    262181        my.wm.panes_list[my.wm.panes_current].prev_window() 
    263182 
    264     def S_M4_space(my, event): 
     183    def S_M1_space(my, event): 
    265184        my.wm.panes_list[my.wm.panes_current].next_window() 
    266185 
    267     def M4_k(my, event): 
     186    def _getapp(my, node): 
     187        getapp(my.wm.panes_list[my.wm.panes_current], node.get('title'), 
     188               node.get('command')) 
     189 
     190    def M1_a(my, event): 
     191        view_menu(my.wm.panes_list[my.wm.panes_current], 
     192                  XML_controller(my.menus.find('functionmenu'), 
     193                                 dict(getapp=my._getapp))) 
     194 
     195    def M1_A(my, event): 
     196        def run(node): my.wm.system('%s &' % node.get('command')) 
     197        view_menu(my.wm.panes_list[my.wm.panes_current], 
     198                  XML_controller(my.menus.find('namemenu'), 
     199                                 dict(getapp=my._getapp, run=run))) 
     200 
     201    def M1_c(my, event): 
    268202        my.wm.panes_list[my.wm.panes_current].window.delete(1) 
    269203 
    270     def S_M4_k(my, event): 
     204    def M1_l(my, event): 
     205        my.wm.system('xscreensaver-command -activate') 
     206 
     207    def M1_i(my, event): 
     208        windowmenu(my.wm.panes_list[my.wm.panes_current], cfilter.iconified) 
     209 
     210    def M1_I(my, event): 
     211        my.wm.inspect_enable() 
     212        my.wm.system('xterm -title Inspector -e inspect_plwm &') 
     213 
     214    def M1_k(my, event): 
    271215        my.wm.panes_list[my.wm.panes_current].window.destroy() 
    272216 
    273     def M4_m(my, event): 
    274         MenuKeys(my.wm, event.time) 
    275  
    276     def M4_M(my, event): 
    277         def nop(): 
    278             pass 
    279  
    280         codemenu(my.wm.panes_list[my.wm.panes_current], 
    281                  {"Next pane (tab)": (my.M4_Tab, (event,)), 
    282                   "Previous pane (shift tab)": (my.S_M4_Tab, (event,)), 
    283                   "Maximize (1)": (my.M4_1, (event,)), 
    284                   "Command (!)": (my.M4_exclam, (event,)), 
    285                   "Browser (b)": (my.M4_b, (event,)), 
    286                   "Clipboard (c)": (my.M4_c, (event,)), 
    287                   "Directory search (d)": (my.M4_d, (event,)), 
    288                   "Emacs (e)": (my.M4_e, (event,)), 
    289                   "Firefox (f)": (my.M4_f, (event,)), 
    290                   "Scroogle search (g)": (my.M4_g, (event,)), 
    291                   "Gnucash (G)": (my.M4_G, (event,)), 
    292                   "Image search (I)": (my.M4_I, (event,)), 
    293                   "IMDB search (i)": (my.M4_i, (event,)), 
    294                   "J-Pilot (j)": (my.M4_j, (event,)), 
    295                   "Thesaurus search (t)": (my.M4_t, (event,)), 
    296                   "Webster search (w)": (my.M4_w, (event,)), 
    297                   "Pane renumber (=)": (my.M4_equal, (event,)), 
    298                   "Pull window (')": (my.M4_quoteright, (event,)), 
    299                   'Goto window (")': (my.M4_quotedbl, (event,)), 
    300                   "Next window (shift space)": (my.M4_space, (event,)), 
    301                   "Previous Window (space)": (my.S_M4_space, (event,)), 
    302                   "Close window (k)": (my.M4_k, (event,)), 
    303                   "Kill window (K)": (my.S_M4_k, (event,)), 
    304                   "Menus (m)": (my.M4_m, (event,)), 
    305                   "This menu (M)": (nop, ()), 
    306                   "Quit (Q)": (my.M4_Q, (event,)), 
    307                   "Force window resize (r)": (my.M4_r, (event,)), 
    308                   "Iconify window (x)": (my.M4_x, (event,))}) 
    309  
    310     def M4_Q(my, event): my.wm.quit() 
    311  
    312     def M4_r(my, event): 
    313         my.wm.panes_list[my.wm.panes_current].force_window() 
    314  
    315     def M4_v(my, event): 
    316         getapp(my.wm.panes_list[my.wm.panes_current], "TightVNC", "vncviewer") 
    317  
    318     def M4_x(my, event): 
    319         my.wm.panes_list[my.wm.panes_current].iconify_window() 
    320  
    321  
    322 class MenuKeys(keys.KeyGrabKeyboard): 
    323     "Menus, with a timeout." 
    324  
    325     def a(my, event): 
    326         appmenu(my.wm.panes_list[my.wm.panes_current], 
    327                 {'clipboard': 'xclipboard', 
    328                  'fxtv': 'fxtv', 
    329                  'w3m': 'w3m', 
    330                  'skipstone': 'skipstone'}) 
    331         my._cleanup() 
    332  
    333     def A(my, event): 
    334         appmenu(my.wm.panes_list[my.wm.panes_current], 
    335                 {'mixer': 'xgmixer', 
    336                  'console': 'xconsole -daemon', 
    337                  'gkrellm': 'gkrellm', 
    338                  'xterm': 'xterm -ls'}) 
    339         my._cleanup() 
    340  
    341     def b(my, event): 
    342         windowmenu(my.wm.panes_list[my.wm.panes_current]) 
    343         my._cleanup() 
    344  
    345     def c(my, event): 
     217    def M1_m(my, event): 
     218        def itunes(node): os.system('itunes %s' % node.get('command')) 
     219        view_menu(my.wm.panes_list[my.wm.panes_current], 
     220                  XML_controller(my.menus.find('itunesmenu'), 
     221                                 dict(itunes=itunes))) 
     222 
     223    def M1_n(my, event): 
    346224        pane = my.wm.panes_list[my.wm.panes_current] 
    347225        width, height = pane.screen.message_make("Current pane %d" % \ 
     
    349227        pane.screen.message_display((pane.width - width) / 2 + pane.x, 
    350228                                   (pane.height - height) / 2 + pane.y) 
    351         my._cleanup() 
    352  
    353     def i(my, event): 
    354         windowmenu(my.wm.panes_list[my.wm.panes_current], cfilter.iconified) 
    355         my._cleanup() 
    356  
    357     def m(my, event): 
    358         def inspect(wm): 
    359             wm.inspect_enable() 
    360             wm.system('xterm -title Inspector -e inspect_plwm &') 
     229 
     230    def M1_p(my, event): 
     231        panesmenu(my.wm.current_screen) 
     232 
     233    def M1_r(my, event): 
     234        my.wm.panes_list[my.wm.panes_current].force_window() 
     235 
     236    def M1_R(my, event): 
     237        def reload_menus(): 
     238            my.menus = load_menus(my.menu_file) 
    361239 
    362240        codemenu(my.wm.panes_list[my.wm.panes_current], 
    363                    {'inspect': (inspect, (my.wm,)), 
    364                     'save': (my.wm.panes_save, ()), 
    365                     'restore': (restore, (my.wm,))}) 
    366         my._cleanup() 
    367  
    368     def p(my, event): 
    369         panesmenu(my.wm.current_screen) 
    370         my._cleanup() 
    371  
    372     def w(my, event): 
     241                 {'1: Restore': (restore, (my.wm,)), 
     242                  '2: Reload': (reload_menus, ()), 
     243                  '3: Restart': (os.execvp, (sys.executable, 
     244                                             [sys.executable] + sys.argv)), 
     245                  '4: Quit': (my.wm.quit, ()) 
     246                 }) 
     247 
     248    def M1_s(my, event): 
     249        def dillo(url): 
     250            my.wm.system("dillo '%s' &" % url) 
     251  
     252        def dowebsearch(node): 
     253            if node.get('images'): 
     254                websearch(pane, node.get('label'), paneWindow, node.get('url'), dillo) 
     255            else: 
     256                websearch(pane, node.get('label'), paneWindow, node.get('url')) 
     257 
     258        pane = my.wm.panes_list[my.wm.panes_current] 
     259        menu = XML_controller(my.menus.find('websearches'), dict(search=dowebsearch)) 
     260        add_keys(menu) 
     261        view_menu(pane, menu) 
     262 
     263    def M1_S(my, event): 
     264        my.wm.panes_save() 
     265        pane = my.wm.panes_list[my.wm.panes_current] 
     266        width, height = pane.screen.message_make("Saved panes configuration") 
     267        pane.screen.message_display((pane.screen.root_width - width) 
     268                                     / 2 + pane.screen.root_x, 
     269                                    (pane.screen.root_height - height) 
     270                                     / 2 + pane.screen.root_y) 
     271 
     272    def M1_w(my, event): 
     273        windowmenu(my.wm.panes_list[my.wm.panes_current]) 
     274 
     275    def M1_W(my, event): 
    373276        pane = my.wm.panes_list[my.wm.panes_current] 
    374277        windowmenu(pane, panes.panefilter(pane)) 
    375         my._cleanup() 
    376  
    377     def W(my, event): 
    378         windowmenu(my.wm.panes_list[my.wm.panes_current], 
    379                    lambda w: not (w.panes_pane and w.panes_pane.window == w)) 
    380         my._cleanup() 
    381  
    382     def M4_m(my, event): 
    383         codemenu(my.wm.panes_list[my.wm.panes_current], 
    384                  {"applications (a)": (my.a, (event,)), 
    385                   "startup apps (A)": (my.A, (event,)), 
    386                   "all windows (b)": (my.b, (event,)), 
    387                   "current pane (c)": (my.c, (event,)), 
    388                   "iconfified (i)": (my.i, (event,)), 
    389                   "manager ops (m)": (my.m, (event,)), 
    390                   "panes (p)": (my.p, (event,)), 
    391                   "open in pane (w)": (my.w, (event,)), 
    392                   "all in pane (W)": (my.W, (event,))}) 
    393         my._cleanup() 
    394  
    395     C_g = Any_Escape = keys.KeyGrabKeyboard._timeout 
    396      
     278 
     279    def M1_x(my, event): 
     280        my.wm.panes_list[my.wm.panes_current].iconify_window() 
     281 
     282 
     283def add_keys(menu): 
     284    """Add shortcuts keys to the menu.""" 
     285 
     286    for label in menu.keys(): 
     287        node = menu[label] 
     288        key = node.get('shortcut') 
     289        if key: 
     290            nl = '%s: %s' % (key, label) 
     291            menu[nl] = menu[label] 
     292            del menu[label] 
     293 
    397294 
    398295def restore(wm): 
     
    401298    pane = wm.panes_list[0] 
    402299    pane.maximize() 
    403     wm.panes_list[1].maximize() 
    404  
     300         
    405301    # Disconnect all windows from panes to avoid displaying everything 
    406302    # that's about to happen. wm.panes_restore() will put things back. 
     
    408304        c.panes_pane = None 
    409305 
    410     # Disconnect the two remaining panes from their windows as well. 
     306    # Disconnect any remaining panes from their windows as well. 
    411307    pane.window = None 
    412     wm.panes_list[1].window = None 
     308 
     309    # If we don't have Xinerama working, fake it by splitting the one 
     310    # *big* screen. 
     311    pane.vertical_split(1920. / 3520.) 
    413312 
    414313    # Create the panes 
     
    416315    pane.horizontal_split(.06) 
    417316    pane.vertical_split(.75) 
    418     pane.horizontal_split(.37) 
    419     pane.horizontal_split(.77) 
     317    pane.horizontal_split(.06) 
     318    pane.horizontal_split(.45) 
    420319    pane = wm.panes_list[4] 
    421320    pane.horizontal_split(.42) 
     
    435334    wm.panes_goto(8) 
    436335    wm.panes_number(5) 
    437     #wm.panes_goto(6) 
    438     #wm.panes_number(6) 
    439336    wm.panes_goto(8) 
    440337    wm.panes_number(7) 
    441338     
    442339    # Set up the second screen 
    443     wm.panes_list[8].vertical_split() 
     340    #wm.panes_list[7].vertical_split() 
    444341 
    445342    # And make the world sane 
  • trunk/plwm/input.py

    r188 r193  
    2323 
    2424from Xlib import X, Xatom 
    25 from Xlib.keysymdef import latin1 
    26 from keys import KeyGrabKeyboard 
     25from keys import KeyGrabKeyboard, allmap 
    2726from wmanager import Window 
    2827 
     
    4847    _done - run action on the current string 
    4948 
    50     _abort - exit without doing anything""" 
     49    _abort - exit without doing anything 
     50 
     51    _history_up - scroll to newer events 
     52 
     53    _history_down - scroll to older events""" 
    5154 
    5255    timeout = None 
    5356 
    54     def __init__(my, handler, display, initial=''): 
     57    def __init__(my, handler, display, history): 
    5558        """Init with a handler and display. 
    5659 
    5760        handler is a handler object appropriate for KeyGrabKeyboard. 
    5861        display has show(left, right), do(string) and abort() methods. 
    59             both abort() and do() should clean up the object.""" 
     62            both abort() and do() should clean up the object. 
     63        history is a list of strings we let the user scroll through.""" 
    6064 
    6165        KeyGrabKeyboard.__init__(my, handler, X.CurrentTime) 
    6266        my.display = display 
    6367        my.handler = handler 
     68        my.history = history 
     69        my.history_index = len(history) 
    6470        my.left = "" 
    65         my.right = initial 
     71        my.right = "" 
    6672        if isinstance(handler, Window): 
    6773            my.selection = my.wm.display.intern_atom("SELECTION") 
     
    127133 
    128134    def _done(my, event): 
    129         my.display.do(my.left + my.right) 
     135        res = my.left + my.right 
     136        my.history.append(res) 
     137        my.display.do(res) 
    130138        my.wm.dispatch.remove_handler(my) 
    131139        my._cleanup() 
     
    136144        my._cleanup() 
    137145 
    138 for c in dir(latin1): 
    139     if len(c) > 3 and c[:3] == 'XK_': 
    140         setattr(InputKeyHandler, c[3:], InputKeyHandler._insert) 
    141  
     146    def _history_up(my, event): 
     147        if len(my.history): 
     148            if my.history_index > 0: 
     149                my.history_index -= 1 
     150                my.left = my.history[my.history_index] 
     151                my.right = "" 
     152                my.display.show(my.left, my.right) 
     153 
     154    def _history_down(my, event): 
     155        if len(my.history): 
     156            if my.history_index <(len(my.history)-1): 
     157                my.history_index += 1 
     158                my.left = my.history[my.history_index] 
     159                my.right = "" 
     160                my.display.show(my.left, my.right) 
     161 
     162allmap(InputKeyHandler, InputKeyHandler._insert) 
    142163 
    143164class inputWindow: 
     
    149170    borderwidth = 3 
    150171    bordercolor = "black" 
    151  
    152     def __init__(my, prompt, screen, length = 30): 
     172    history = [] 
     173 
     174    def __init__(my, prompt, screen, length=30): 
    153175 
    154176        if not prompt: prompt = ' '     # We have problems if there's no prompt, so add one. 
     
    184206        my.window.dispatch.add_handler(X.Expose, my.redraw) 
    185207 
    186     def read(my, action, handlertype, x = 0, y = 0, initial=''): 
     208    def read(my, action, handlertype, x=0, y=0): 
    187209        "Open the window at x, y, using handlertype, and doing action." 
    188210 
     
    191213        my.window.configure(x = x, y = y, width = width, height = height) 
    192214        my.window.map() 
    193         handlertype(my.window, my, initial) 
     215        my.window.get_focus(X.CurrentTime) 
     216        handlertype(my.window, my, my.history) 
    194217 
    195218    def raisewindow(my, event): 
     
    237260    "Class to get input via the modewindow." 
    238261 
     262    history = [] 
     263 
    239264    def __init__(my, prompt, screen, length = None): 
    240265        # ignore length argument 
     
    245270        my.action = action 
    246271        my.status_msg = my.screen.modestatus_new(my.prompt + "_") 
    247         handlertype(my.screen.modewindow_mw.window, my) 
     272        handlertype(my.screen.modewindow_mw.window, my, my.history) 
    248273 
    249274    def show(my, left, right): 
  • trunk/plwm/keys.py

    r179 r193  
    1 # $Id: keys.py,v 1.9 2005-08-10 13:30:37 mwm Exp $ 
     1# $Id: keys.py,v 1.10 2007-07-14 07:38:13 mwm Exp $ 
    22# 
    33# keys.py -- Base keypress handlers 
     
    2020 
    2121from Xlib import X, XK 
     22from Xlib.keysymdef import latin1 
    2223import string 
    2324import wmanager 
     
    142143             
    143144         
    144         wmanager.debug('mem', 'Initing keyhandler %s', self) 
     145&n