SINGER@SPAR-20.ARPA (David Singer) (09/03/87)
Date: Wed 2 Sep 87 13:23:54-PDT From: David Singer <SINGER@SPAR-20.ARPA> Subject: Keyboard auto-repeat To: news-makers@brillig.umd.edu Cc: evans@SUN.COM, news-makers@SPAR-20.ARPA Here's a simple implementation of keyboard auto-repeat; it should be loaded before anything that wants the value of ascii_keymap (I load it in my user.ps). The initial and repeat delay is tunable through the REPEAT_private dictionary. Note that simply loading this file does NOT turn on auto-repeat; use the autorepeat function to start it (and stoprepeat to stop it). %%% %%% Auto-repeat the keyboard. %%% %%% D.W. Singer %%% Schlumberger Palo Alto Research. %%% %%% Create a process which listens for keyboard down %%% transitions; when one happens, remember the key and %%% keystate, and start a timer event. When the timer fires %%% send out a new event and re-start it. When the up %%% transition happens, cancel the timer. /REPEAT_private 30 dict begin /initial_delay 1 3 div 60 div def % 1/3 second /repeat_delay 1 20 div 60 div def % 20 per second /repeater_process null def /repeater_event null def /interest_event null def currentdict end def %% Fix ascii_keymap so that it also contains encoded ascii, %% so that events can also be distributed with ascii strokes %% directly in them. ascii_keymap maxlength 256 eq { /ascii_keymap ascii_keymap 512 dict copy def 0 1 255 { ascii_keymap exch dup put } for } if /autorepeat { REPEAT_private /repeater_process { newprocessgroup REPEAT_private begin /interest_event createevent def interest_event /Action [ /DownTransition /UpTransition /AutoRepeat ] put interest_event /Priority 10 put interest_event /Name ascii_keymap put %%interest_event /Name null put interest_event /Canvas null put interest_event /Exclusivity true put interest_event expressinterest /repeater_event null def { awaitevent dup /Action get /UpTransition eq { %%(stopping\n) print redistributeevent repeater_event null eq not { repeater_event recallevent /repeater_event null def } if } { repeater_event null eq not { %%(cancelling\n) print repeater_event recallevent /repeater_event null def } if /repeater_event createevent def [ /Action /Name /TimeStamp /ClientData /XLocation /YLocation %%/Canvas ] { 2 copy get repeater_event 3 1 roll put } forall redistributeevent repeater_event /ClientData get /AutoRepeat eq %%repeater_event /Action get /AutoRepeat eq { %%(repeating %\n) [ repeater_event /Name get ] printf repeater_event /TimeStamp repeater_event /TimeStamp get repeat_delay add put } { %%(starting %\n) [ repeater_event /Name get ] printf repeater_event /TimeStamp repeater_event /TimeStamp get initial_delay add put } ifelse repeater_event /ClientData /AutoRepeat put repeater_event /Process null put %%repeater_event /Action /AutoRepeat put repeater_event sendevent } ifelse } loop } fork put } def /stoprepeat { REPEAT_private /repeater_process get killprocess } def -------