Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site bbncc5.UUCP Path: utzoo!watmath!clyde!cbosgd!ihnp4!houxm!mhuxt!mhuxr!ulysses!allegra!mit-eddie!think!harvard!bbnccv!bbncc5!jr From: jr@bbncc5.UUCP (John Robinson) Newsgroups: net.emacs Subject: Re: emacs mouse support Message-ID: <1183@bbncc5.UUCP> Date: Mon, 20-Jan-86 16:00:44 EST Article-I.D.: bbncc5.1183 Posted: Mon Jan 20 16:00:44 1986 Date-Received: Thu, 23-Jan-86 08:26:41 EST References: <912@mit-eddie.UUCP> Reply-To: jr@bbncc5.UUCP (John Robinson) Organization: Bolt Beranek and Newman, Cambridge, MA Lines: 233 In reply to the original posting from Ian Hors... (sorry, lost the spelling) - What work, if any, has already been done? I will describe the BBN Bitgraph terminal. This is now available commercially from Forward Technology, called the GTR-01 as I recall, about $3000 quantity one. Back when it was still a BBN product, I worked some on the programming of it, including the mouse support, so I can take the blame or credit for its design in part. I will also describe the emacs-lisp package I wrote for it, available from GNU/Free Software Found. with emacs version 17 and later (bg-mouse.el). - What sorts of mouse events should be included in the protocol? e.g. do we allow chords of buttons, double clicks, etc. Bitgraph defines several possible events, which can each be individually enabled or disabled. They are: button up (left, middle, right) [Note: the GTR-01 has only a 2-button mouse], button down, button quiescent, motion quiescent, delta x, and delta y. Any enabled event causes a mouse report to be sent to the host. Button quiescent allows the terminal to locally detect chords (debouncing is already handled automatically), or the host to count multiple ticks a la the Mac. The last three events are used together. The delta x and delta y define a rectangle from the last reported mouse position. Moving outside of that rectangle causes the appropriate event. This allows gross host tracking for complex actions like dragging or sizing. The quiescent timer can then get the exact position when motion stops. In the elisp I wrote, I use only button-down events. I arranged assignments so that chords do useful second functions (see below). - What do we do about commies who don't have three buttons? I don't know. In using my 3-button mouse, I find that 2 buttons do most of the work, if I count chords. For emacs, you could somehow have modifiers in the form of functions with side-effects (i.e. set a global variable that only the mouse commands see). The obvious one, though, is to use the numeric prefix featues (^U, ESC-nnn) to simulate many buttons. The alternative is multiple keyclicks. I think this is fine for workstation-type environments. For terminals talking to hosts, this may cause excess input-character traffic, resulting in either lagging response (and irate cries from others) or lost characters. I have never tried to see how bad this really can become. I notice that mouse reports (many characters) sometimes are processed slower than individual typed characters under heavy loads - probably due to the biases built into the Unix scheduler to favor interactive jobs. - What should the actual protocol look like? The Bitgraph follows ANSI standard X3.64 for all its private commands and responses. This is what VT100 (mostly) and followers use. The general form is ESC [nnnn [;nnnn]*] . This format is used in both directions over the link. is the character [ for standard commands and the character : for private commands. is a printable non-numeric (and not ";") character that says what the command is. The nnnn are zero or more numeric arguments, decimal, represented with the ASCII characters 0 - 9 (not dense, I know, but that shouldn't be an issue for interactive terminal use). [I had a little exchange with RMS over whether this is good or not. He of courses firmly believes that ESC-[ should mean backward-paragraph and that's that. Although ESC-: has no standard meaning in emacs (or perhaps because of this), he was worried about my establishing a de-facto standard for it. I say good! - at least it is likely to be used a lot because of the ANSI standard.] [Although the Bitgraph is downline-loadable, I don't think I want to use a private version of the terminal program to suit emacs users' tastes - it should use the built-in program if at all possible. Also, not all Bitgraphs are equipped with enough memory for a downloaded program.] I had to write an elisp parser for these commands - I would like to see it become a standard way for emacs interactive commands to find their arguments. Then I could bind, for example, ESC-[-A with this attribute, and the parser would pick up any argument(s) between the [ and the A and pass it (them) to the called function. Then up-arrow (as on the VT100) could be previous-line, while a key that I wanted to be up-5-lines could send ESC-[-5-A and be interpreted without a private elisp function. This is a bad example, I admit. Note that this parser would solve the problem one poster mentioned with respect to the VT-220 function keys, which send ESC-[-nn-~. The bitgraph mouse report looks like: ESC : N1 ; N2 ; N3 ; N4 c where N1 is 2 (there are other possible messages in this group), N2 is the x position is pixels (current region coordinates; default is whole screen) N3 is the Y position, and N4 is the state: 3 bits for buttons that are up 3 bits for buttons that are down (overkill, maybe) 1 bit on if the button event fired 1 bit to tell whether the coordinates are absolute or relative to the last mouse report. In programming the mouse, aside from enabling events, you can: - reposition the mouse cursor on the terminal - set the quiescent timers, in milliseconds (up to 65536 I think) - scale the x and y rates on the mouse - size the mouse x and y motion increments (see below) - set the delta threshold for the delta x and y events - bind the mouse to a region (rectangle on the screen defined previously; defaults to entire screen) - set the initial button state - cause mouse reports to have absolute or relative positions Scaling and increments work this way: the Bitgraph won't consider the mouse to have moved until it has moved scalex pixels in mouse coordinates. Once it has moved this far, it will move incrx pixels in srceen coordinates. Thus you can speed up or slow down mouse motion. But, you can also restrict the mouse's position. Thus, in the elisp package, I set the scalex=incrx=standard character width (9 pixels) and the scaley=incry=standard character height (16 pixels). Now the mouse cursor always aligns itself to the character grid. I use an open 1-character box for the mouse cursor. Reports to the host are still sent in pixels. This is okay, since the host has to know the font size to program it in the first place. Actually, there is a way for it to ask the Bitgrah about the current font's characteristics, so this could be set up dynamically, but I just use the defaults. - What sorts of standard hooks should be incorporated into emacs? See the earlier paragraph about a parser. Another thing I would like to be able to do is have the mouse events dispatch through a keymap. I haven't really looked hard, but I have not yet found a convenient way to do this. So right now the mouse-report just executes a giant case statement to dispath the events and hit-regions. Others have posted ideas about what mouse hits should do. Here is the help from my mouse function: bg-mouse-report: Read and parse BBN BitGraph mouse report, and do what it asks. L-- set dot (cursor) * |---- These functions for mouse hit in a window. --R set mark * | bg-mouse-fast-select-window lets starred commands L-R kill region | L--, -C-, and --R work on any visible window, -C- set dot and yank * | else mouse hit just selects that window. LC- yank-pop -CR or LCR undo | "Scroll bar" is right-hand window column. hit: on modeline on "scroll bar" in minibuffer L-- scroll-up line to top execute-extended-command --R scroll-down line to bottom eval-expression -C- proportional goto-char line to middle suspend-emacs To reprogram the mouse, type ESC : . I use 4 regions: in window, in modeline, in minibuffer (extended-command echo area) and in scrollbar, the rightmost edge of a window (where the continuation characters print). The minibuffer set I almost never use; their typed equivalents are almost always easier since you generally follow them with more typing anyway. Notice the sequences of mouse hits that are possible, such as --R , L-R , LCR which sets the mark, kills the region thus defined, and then undoes the kill, or -C- , LC- , -CR which yanks at the mouse cursor, then does a yank-pop (this can repeat by repeatedly ticking the L (or C) button), then undoes the last one (which could also repeat). The variable bg-mouse-fast-select-window snatches an idea from Symbolics - the idea is that you may want to be able to select another window without dusturbing point or mark in it. It doesn't affect chord commands since they are assumed to follow one-key commands. Modeline and scroll-bar commands work on any window any time, without changing which window is selected. Generally, I put the least-used function of each group on the center button. I find the left and right easier to hit, at least on my (Swiss) mouse. On menus and processes: The Bitgraph has primitives that make pop-up (or pull-down - what's the difference aside from where they appear?) menus pretty efficient. I haven't made the emacs functions to support them yet, but it might be a nice enhancement. I would imagine binding mouse hits to particular menus, then succesive mouse hits would call the indicated function from the menu. The menu would be initialized from a list of pairs, which give the menu entry (string) and the function to call (symbol). Emacs would send the text the first time; then succesive uses of the same menu would blit it onto the screen from off-screen memory. The local mouse tracking can inverse-video one item on the menu until a button push, at which time the host would restore the hidden screen info. The way the program would see this is that the function called from the menu would be given an argument telling which mouse button(s) was (were) used to select it, and where the original mouse hit that invoked the menu in the first place happened. Mostly, I guess these arguments would be ignored. With a terminal, I don't have to think too hard about processes versus emacs - I generally sit in emacs all day and use its windows (e.g. shell mode) as a desktop analog. We also have a window manager process on our Unix machines, however, and it is not integrated with emacs in any way. It thinks it "owns" the mouse and the entire terminal, as does emacs. The region support in the bitgraph might allow for the mouse's actions to be shared among the applications sharing the terminal screen, but this may be hard and require someone, probably thae window manager, to examine all the mouse reports and filter them and then repost them to the right application. Eventually, it becomse hard because you'd really like the multiple regions (windows) on the terminal face to behave like somewhat independent processes that share the terminal line to talk to their counterparts on the host. But the terminal protocol is not yet up to independent streams, so this model breaks down. So, we are left with one host process owning the entire display and manging it for you. For my money, emacs is the best at doing this these days. John Robinson {bbncc5|bbnccv|bbncca}!jr jr@{bbncc5|bbn-unix}