horswill@loon.ai.mit.edu (01/10/86)
From: horswill@loon.ai.mit.edu A few months ago I wrote a quick kluge for the Sun workstation which I called "emacstool". It was simply a copy of the tty window driver which I had modified to send escape sequences when mouse events occurred. I never distributed it, in part because it contained SMI source code and in part because I didn't consider it "finished". After having used it for a while, I have come to believe that it is a very nice way of doing things for two reasons. First, it keeps emacs from having to contain code for talking to a particular window system. Thus the source directories do not have to have files called "mouse_smi.c", and "mouse_apollo.c", and people running emacs from dialup lines need not have all the window system crud in their address space. A second reason why I like the notion of an "ascii mouse" protocol is that it allows me to perform mouse operations even when emacs is not running on a machine with a mouse. For example, I can run emacstool on a sun, login on a vax from emacstool, and then run emacs with the mouse support code loaded, and do all of the things which I can do on a sun on the vax. In addition, if I owned a Macintosh or clone thereof, I could modify my terminal emulator to send the Sun escape sequences and, once again, do all of the things I could do on a Sun over a dialup line. I am now planning on writing a "correct" version of the mouse support code, and in particular, am planning to keep proprietary code out of it so that it may be distributed. I would like to standardize the mouse protocol so that others can use it, and in particular, can start to incorporate mouse support into their emacs packages (e.g. make the middle button visit a file in dired). My questions for the group are thus: - What work, if any, has already been done? - What sorts of mouse events should be included in the protocol? e.g. do we allow chords of buttons, double clicks, etc. - What do we do about commies who don't have three buttons? - What should the actual protocol look like? and, - What sorts of standard hooks should be incorporated into emacs? I would appreciate it if you could include explanations if and when you get into nitty-gritty elisp discussions since I am relatively unfamiliar with elisp. Thanks, Ian Horswill Univ. of Minn. CS Dept.
greg@nosc.ARPA (01/10/86)
From: vis!greg@nosc.ARPA I think its a mistake to have emacs subdivide a single window on a workstation, therefore we don't want an emacs tool of the kind that Ian Horswill suggests. What we want are windowtools to manage the keyboard, mouse and display, and interface to a single emacs job through a standard protocol. If we do it right, I claim this organization will allow (1) multiple display units per user, (2) N mouse buttons with single or multiple clicking, (3) keyboards with or without function keys, (4) proportional fonts, and much more, with a smaller and simpler emacs. A related need is for a process server protocol, so we can combine remote processes with local processes connected to the same emacs job. I only want one emacs job, regardless of how many processes I've got or where they're running. And I want to talk to processes (and manipulate their windows) without regard to where they live. On my display right now I have one huge shelltool containing an emacs job where I'm handling my mail. In a second shelltool I'm tip'ed over to another machine where, underneath another emacs job, I'm doing an ftp and monitoring its performance. I have a third shelltool for scratch work and some additional closed tools (showing as icons) are available when needed. It sounds nice, but is in fact very cumbersome. With one local emacs job in charge, I'd have a more integrated and consistent environment. I'd also get rid of the expense of multiple layers of display management, and windows trapped within windows. Pointing and clicking, cutting and pasting, etc., would be applicable with all objects and done in a consistent manner. Well, I trust that these suggestions will be provocative. I'm willing to start work right away on building such tools, but first we need to have a consensus on how it should be done. What functionality should be pulled out of emacs and put in separate tools, and what protocols shall we use to tie them all together? _Greg J. Greg Davidson Virtual Infinity Systems (619) 452-8059 6231 Branting St; San Diego, CA 92122 greg@vis.uucp ucbvax--| telesoft--| davidson@sdcsvax.uucp decvax--+--sdcsvax--+--vis davidson@ucsd.arpa ihnp4--| noscvax--|
sbm@Purdue.EDU (01/10/86)
From: "Steven B. Munson" <sbm@Purdue.EDU> Since you mentioned the Macintosh, I guess it's appropriate to mention that there is already a public domain multiple window terminal emulator for the Macintosh called UW that supports mouse operations. The mouse protocol is very simple. Each mouse button event (mouse up or mouse down) causes the following five-character sequence to be sent to emacs: <ESC> m <y> <x> <b> where <y>, <x>, and <b> are integers encoded as characters with 32 added to their value to make them printable. <y> and <x> are the row and column where the event occurred, and <b> is a number that indicates whether it was a mouse up or mouse down and what modifier keys were used. The Macintosh has four modifier keys, the shift and caps lock keys and two others, called the option key and the command key (the keyboard can be mapped to use either one as a control key). The bits in <b> indicate whether it was a mouse up or a mouse down and the state of the modifier keys when the event happened. From most significant to least significant, the bits mean: 6 5 4 3 2 1 up down option lock shift command Don't ask me why two separate bits were used to indicate whether it was a mouse up or a mouse down; I didn't design the protocol. Also, the Macintosh has a one-button mouse; if bit 5 indicated whether it was an up or a down and 32 wasn't added to the character before transmission, then there would be 2 more bits in a 7-bit character to indicate which button was used on a multiple button mouse. Notice that the terminal emulator itself doesn't decide in any way what the mouse events mean; it just sends the raw events to the host. Since emacs gets both mouse down and mouse up events, it is possible not only to position the cursor by clicking, but also to do things like selecting or deleting a range of characters by clicking and dragging over them (in my case, drag selects them, or copies them to the Kill buffer, and shift-drag deletes them) and resizing emacs windows by dragging their mode lines. This requires that the mlisp package keep the last value of <x>, <y> and <b> to determine whether the action was a click or a drag (whether the mouse moved between mouse down and mouse up). The mlisp package can also detect whether the mouse event was in the scroll bar of the Macintosh window and scroll by pages or lines or do goto-percent-of-file, depending on the state of the modifier keys. Steve Munson sbm@Purdue.EDU sbm@Purdue.CSNET ----------
jqj@cornell.UUCP (J Q Johnson) (01/12/86)
jr@bbnccv.uucp (he has an arpa addr too, but I've lost it) did a very nice package for the Bitgraph mouse based on the same premise -- an ASCII mouse. I used his protocol and implemented support for the mouse in an Interlisp-D terminal emulation window on a Dandelion. Some comments: 1/ there are 2 separate issues, the design of the mouse protocol, and the assignment of functions to mouse buttons. When implementing the support code in emacs the 2 should be kept very separate so that a user may independently replace either the mouse protocol (when s/he moves to a different workstation that supports different protocols) or the functions (when s/he decides that chording LRM while holding down META should do something different on all terminals s/he uses). 2/ the issue of whether such a protocol is a good idea at all is a canard. It is. There will always be cases where I want to log in to a remote system (or to several remote systems in different windows) from my multi- window workstation, and run gnuemacs in a terminal emulation window. In such an environment I definitely don't WANT gnuemacs to take over complete control of my display (I want to see my local desk accessories), but I do want my mouse. 3/ there is no standard for mouse protocols. Each of the ascii mouse makers (for attachement to your PC) uses a different protocol. I very much like the bitgraph protocol; I think it is well thought out and very general. One problem with it for Emacs use is that it transmits the mousecursor position in pixels, which requires that the program (Emacs) know the size of the font in the window. Whatever protocol you use, it should be fairly general; it should be able to handle arbitrarily large windows (hence the mac protocol published in a previous message is bad), a fairly large number of logical buttons, chording, button-down and button-up events, window entry- and exit- events, etc. For emacs purposes I don't think it's necessary for the program to be able to track the mouse, but in general that's a nice feature (allowing dragged highlighting, etc.), and so the protocol should also support as an option periodic mouse position-report events. Explicitly unsupported, I think, should be local popup menus (pulldown might be ok). 4/ the function-bindings should be designed to degrade gracefully to mice with different characteristics, notably different numbers of buttons. Many mice, e.g. on the Mac, are 1-botton; others, e.g. on the Dandelion, are 2-button. So the command set should be arranged in a hierarchy. On the other hand, you can use active regions very effectively to increase the number of commands: in jr's mouse support, the mouse-clicks mean different things depending on whether you are in (1) the text of a window (2) a mode line, (3) the minibuffer, (4) a scroll bar which he implements as the rightmost (unused in gnuemacs except as a separator) column of a window. Pointing and scrolling seem to be the most important mouse functions to implement, with deleting and undeleting a marked region immediately following. Note also that the command set needs to make provision for local mouse functions, e.g. window-world control. The usual way to handle this is that the workstation's mouse support is modified so that mouseclicks in the window's title or border are interpreted as window-world manipulation commands, while clicks in the body of the window are sent to the host. However, this gives up the ability to cut from one window and stuff into a different terminal emulation window (which may perhaps be on a different system).
horswill@moose.ai.mit.edu (01/14/86)
From: horswill@moose.ai.mit.edu Greg Davidson is quite right that it would be nice to integrate emacs with the sun (or other) window system in the manner he described. While I am not sure exactly what the process server protocol is intended to do, I do like the idea of having one emacs job controlling everything very much, and I am often annoyed by not being able to spawn multiple shells or do a grep concurrent with a compilation. The notion of having emacs control everything else is similar to the Apollo Aegis notion of the "display manager", except that it would be more highly programmable. In the mean time, I am still going to work on the simple mouse protocol however since my free time is quite limited and the simpler protocol can be implemented very quickly. -Ian
davidson@sdcsvax.UUCP (J. Greg Davidson) (01/14/86)
From: jqj@cornell.UUCP (J Q Johnson) Subject: Re: emacs mouse support Date: 12 Jan 86 09:50:27 GMT Organization: Cornell Univ. CS Dept. 1/ there are 2 separate issues, the design of the mouse protocol, and the assignment of functions to mouse buttons. I agree. In fact, I'm not certain that the issue of buttons can be or need be separated from the issue of keyboard function keys or keystrokes in general. On my SUN, some tools uses SHIFT with mouse buttons (despite having 3 buttons), and I know the Mac really goes in for this. Between the number of ways of stroking different mice, and modulation with bucky bits and prefixes, we have a pretty open universe. What if we let mouse buttons cause arbitrary keystrokes to be emitted, but followed by a location sequence in a standard form? Users can bind standard functions to the former which read and interpret the latter. Is this sufficient? 2/ the issue of whether such a protocol is a good idea at all is a canard. It is. There will always be cases where I want to log in to a remote system (or to several remote systems in different windows) from my multi- window workstation, and run gnuemacs in a terminal emulation window. In such an environment I definitely don't WANT gnuemacs to take over complete control of my display (I want to see my local desk accessories), but I do want my mouse. Oh dear, I hope that this is not a comment on my recent windowtool proposal. Its redundant for EMACS to be doing window management on a system which has a custom window manager already. Its equally mistaken for EMACS to take over the display as it is for it to make crude windows inside of a terminal emulation window. I propose that when EMACS wants a window, it ask the window manager for one. On a non-workstation, a default window manager would be used, running the same code EMACS runs now, but through communications channels. On a workstation, a simpler window manager would pass the requests to the workstation's window system, e.g., suntools. Of course, there's no requirement that all windows on the screen connect to EMACS, thought I think that this would be natural for windows containing text. _Greg
pz@emacs.UUCP (Paul Czarnecki) (01/16/86)
<eat it> Mouse Protocol First off, I am an employee of Uniworks Inc. At Uniworks I have written a mouse interface to Emacs. A lot of the design issues discussed in these articles (and probably future ones) are issues that I also had to handle. These issues are not specific to our product, they could apply to ANY ascii window manager with a mouse. See the disclaimer at the bottom. In <912@mit-eddie.UUCP> Ian Horswill writes: H> In <914@mit-eddie.UUCP> J. Greg Davidson writes: D> H> A few months ago I wrote a quick kludge for the Sun workstation which H> I called "emacstool". It was simply a copy of the tty window driver H> which I had modified to send escape sequences when mouse events H> occurred. ... H> A second reason why I like the notion of an "ascii mouse" protocol is H> that it allows me to perform mouse operations even when emacs is not H> running on a machine with a mouse. For example, I can run emacstool H> on a sun, login on a vax from emacstool, and then run emacs with the H> mouse support code loaded, and do all of the things which I can do on H> a sun on the vax. For many of the same reasons I also wrote an "emacstool" that talks to Emacs via a pipe. Dumb terminals don't have to use it , system dependent code is also isolated. (The bit about remote usage is cute, I never thought of that!) A disadvantage is that the emacstool process does not know about emacsy things. Since the emacstool process knows about SunWindows it is the emacstool process that draws graphic icons. Doing things like throwing up an hourglass during a file IO are cute but not possible under this implementation. H> My questions for the group are thus: H> - What work, if any, has already been done? Almost completed here. (Uniworks, Inc.) Several pre-release versions are already out and being used. H> - What do we do about commies who don't have three buttons? 3 buttons? Is that all? The Sun software makes allowances to 10 button mice! Alas, I did not encode for this (see the protocol below). Really though, I don't know what to do. A user with less buttons on his mouse will have to give up some functionality, the protocol should be able to handle it. (mine doesn't) H> - What should the actual protocol look like? and, I send: <MA>xxxxyyyy<PM><e> where <MA> Bound to Mouse Autoargument. This tells Emacs to start collecting numbers. This is just like <ESC> or C-U . xxxx The x coords of the mouse in PIXELS! not characters. This gives a finer resolution to certain positioning jobs. I also found it much easier to work with since the size of the characters should be hidden from emacstool. (emacstool is NOT a text editor, it is only a mouse io handler) yyyy This is the y coords of the mouse in PIXELS. <PM> is bound to Prefix Mouse which says that a mouse command is occurring and to read the next character which has that event encoded in it. <e> The event. It is bit encoded like: r m1 m2 n1 n2 l m r where: r is reserved m1,m2 is the two bit encoding for the MEOW value. These are zero in the transmission over the pipe. They are set by the Emacs process upon receipt. n1,n2 Is the two bit encoding for the number of clicks. The only exception to this is that a Still event is encoded as 1 click (even though none occurred) l,m,r These bits are set if that button took part in the event. The encoding of 0 0 0 1 1 0 0 0 is reserved for an error condition. This is sent if an illegal mouse event occurs. Of course MA, and PM are user settable to any single keystroke that you want. (never tried it but I guess you could make them multiple keystrokes) This protocol is fat. I will probably be encoding the xxxxyyyy stuff down into 4 characters. (pack them) I should also warn that this protocol lacks a lot. You cannot do shift, meta, and contol mouse events, nor can you give a mouse event a numeric argument. See my other article on what kind of events this generates. H> - What sorts of standard hooks should be incorporated into H> emacs? I really don't see the need for them. Since Emacs is keystroke driven and the mouse sends keystroke sequences, only the fact that certain commands are bound to mouse events are what signify mouse events. After the emacs process gets them they are no longer special. How can we have hooks for single character events? If someone makes a good case for Mouse Hooks I will add them. D> I think its a mistake to have emacs subdivide a single window on a D> workstation, therefore we don't want an emacs tool of the kind that D> Ian Horswill suggests. What we want are windowtools to manage the D> keyboard, mouse and display, and interface to a single emacs job D> through a standard protocol. I guess I would have to agree that this is the best theoretical approach but I think the tool process way is superior for implementation reasons. Doing separate processes is MUCH faster to do. (I mean in development time, not execution speed). I'll grant that your approach could (should) be the next generation in text editing engines but adding mice to CCA EMACS and Gnuemacs are both retrofits to existing technology. Under the multi process scheme a lot of Emacs features fall into place automatically. The dynamic help feature does not have to be touched. The keystroke recovery feature does not have to be touched. D> If we do it right, I claim this organization will allow (1) multiple D> display units per user, (2) N mouse buttons with single or multiple D> clicking, (3) keyboards with or without function keys, (4) D> proportional fonts, and much more, with a smaller and simpler emacs. ok, so your emacs gets smaller. But remember TANSTAAFL! Your `windowtools' would get larger. I must admit that the above with process server control would be really good. But it would not be TODAY. The idea of one, just one, emacs job is grand. (particularly since, as you mentioned, it would eliminate several layers of display management) Now how portable is this all going to be? With a separate process architecture, all you must do to port is rewrite the tool. This involves learning only a rudimentary knowledge of the window system. What you are proposing requires an in-depth knowledge of the window system. pZ Disclaimer: I am an employee of Uniworks Inc. What I have said here could be considered to be of a commercial nature. I don't think that this is the case. I tried to stick to technical issues related to mouse support of a generic Emacs. The facts represented in this article are the current official statement of Uniworks regarding mouse support for CCA EMACS. These are subject to change without notice. The opinions expressed in this article are my own and are not necessarily shared by anybody else at Uniworks. Anybody is free is use the ideas expressed in this article. (I would be immensely flattered it this happened.) You cannot suppress ideas. The code, however, you will have to pay for. -- -- My wife ran off with my best friend, and I miss him. Paul Czarnecki Uniworks, Inc. decvax!{cca,wanginst!infinet}!emacs!pz 20 William Street emacs!pz@cca-unix.ARPA Wellesley, MA 02181 (617) 235-2600
pz@emacs.UUCP (Paul Czarnecki) (01/16/86)
<eat it> Mouse Bindings First off, I am an employee of Uniworks Inc. At Uniworks I have written a mouse interface to Emacs. A lot of the design issues discussed in these articles (and probably future ones) are issues that I also had to handle. These issues are not specific to our product, they could apply to ANY ascii window manager with a mouse. See the disclaimer at the bottom. In <912@mit-eddie.UUCP> Ian Horswill writes: H> H> - What sorts of mouse events should be included in the protocol? H> e.g. do we allow chords of buttons, double clicks, etc. Since the Emacs user is picky (ok, sophisticated), I did not want to limit in any way the possible mouse events. Of course I had to in practice but I think I covered a lot of ground. Chords, multiples, multiple chords and null events (The mouse becoming still) are all permitted. The click interval is user settable. The maximum number of single button events is 4 clicks per button. These are the possible mouse events. L, M, R, LM, LR, MR, LMR, 2L, 2M, 2R, 2LM, 2LR, 2MR, 2LMR, 3L, 3M, 3R, 3LM, 3LR, 3MR, 3LMR, 4L, 4M, 4R, 4LM, 4LR, 4MR, 4LMR, 0 (still event) I have also divided the screen up into 4 areas: The Mode Line, the Echo Area, the Other Window, and the current Window. I call this the MEOW value. A mouse command will have a different action depending on where it was executed. For example, left clicking once in the Current Window will place the Emacs cursor where the mouse cursor is. However, this action is meaningless if done on the Mode line. Rather than just give an error I decided to do something useful. Left clicking once in the Mode line will go to the percentage down in the file that the mouse cursor is over in the mode line. If you are two thirds of the way from the left edge in the Mode line, a left click will take you two thirds of the way through the file. (This screen division is very similar to what I saw on the net a couple of months ago for the BBN Bitgraph, lost the attribution, sorry) This is almost like Macintosh sensitive areas (where click the little upper left box will close the window, dragging the bottom or right elevators will scroll the window). I have also divided the screen up into sensitive areas. Of course this is much cruder than the Mac because I hardly ever draw pretty little icons. Since using the mouse is expensive, (you have to remove your hands from the keyboard) commands placed on the mouse should be `worth it'. They should need positioning information or be part of a keystroke idiom that contains positioning information. For example, "Place the Emacs point at the mouse cursor" need positioning information. It is a natural candidate for mouse binding. On the other hand, "Place the killed region into the buffer at point" is not directly position dependent, but it is part of the whole cut/move/paste idiom. This also makes it a candidate for mouse binding. As I mentioned earlier, the mouse performs different actions based on where it is located on the screen. Here are the bindings that I use. Current Window Mode Line Echo Area Other Window L Set Point Goto % Shell in a Buffer L2 Set Mark Goto Begining Push to Shell L3 X Point & Mark Goto End Signal Shell L4 Point to Q-Reg Menu (NYI) M HIX Scroll Redisplay at Top Dired M2 HIX Grow Window Redis at Bottom Info M3 HIX Shrink Window Execute Minibuffer M4 Make R Kill Region Save File Tool Hide R2 Yank Region Save All Files Tool Close R3 Fill Region Append to File Tool Expose R4 Filter Region Unmodify Buffer Tool Open LMR Exit Exit Exit Still Current Window Null Null Note how all of the commands are grouped logically together. Since so much can be done with the mouse it must be easy to use/remember. The groupings are: placing moving Shell windows redisplay Sub systems regions Files Tool operations I also tried to organize the groups logically. Window actions take place in a window, Mode line actions (usually) relate to the items in the mode line, Echo area actions relate to "system" functions. Some don't fit (Menu and Make for example) Some of these were placed for other reasons (Exit and Current Window). Exit I wanted hard to type, hence the 3 button chord. And Current Window is the default operation (sort of) for changing Sun Windows. You just place the mouse cursor inside of the window that you want to be current. The only command set that might be confusing are the HIX commands. When a HIX command executes it determines the HIX value of the current position. HIX command will perform the action in the HIX direction. A HIX value can be one of UP, Down, Left, or Right. To determine the HIX value divide the window into four sectors by drawing an invisible 'H', 'I', or an 'X' over the screen. The directions (UDLR) map to a sector. For example, if the HIX character is set to 'I' (the default), then clicking middle once in the bottom third of the window will scroll that window down, middle clicking once in the top third of the window will scroll that window up. Clicking middle once in the left half (but not the top or bottom third will scroll that window left. It is important to remember that all of these bindings are not cast in stone. The user can rebind them on the fly or in an init file. pZ Disclaimer: I am an employee of Uniworks Inc. What I have said here could be considered to be of a commercial nature. I don't think that this is the case. I tried to stick to technical issues related to mouse support of a generic Emacs. The facts represented in this article are the current official statement of Uniworks regarding mouse support for CCA EMACS. These are subject to change without notice. The opinions expressed in this article are my own and are not necessarily shared by anybody else at Uniworks. Anybody is free is use the ideas expressed in this article. (I would be immensely flattered it this happened.) You cannot suppress ideas. The code, however, you will have to pay for. -- -- My wife ran off with my best friend, and I miss him. Paul Czarnecki Uniworks, Inc. decvax!{cca,wanginst!infinet}!emacs!pz 20 William Street emacs!pz@cca-unix.ARPA Wellesley, MA 02181 (617) 235-2600
manheime@nbs-amrf.UUCP (Ken Manheimer) (01/17/86)
I've been meaning to post various gadgets and modifications i've developed for the local installation of emacs, which happens to be Unipress' (out of gosling's) Emacs V 2.01. One of the more fun efforts involved employing the fairly rudimentary handles Unipress provided to the Sun mouse (to better effect than the trivial routines provided in ../maclib/D.term/sun.ml with the distribution). The most interesting aspect in this effort, for me, was deciding upon the most suitable functions to implement, given the handles i had. The results are mixed. As with many of the tweaks Unipress provided to incorporate features of the Sun window system within emacs (e.g. dynamic resizing of the emacs session's window), the concepts seem attractive but in practice the gadgets aren't particularly important. On the other hand, i am still pleased with the balance of functionality i wound up with; this may be due to that syndrome wherein programmers are convinced of the aesthetics of their programs regardless of their ultimate practical worth... (And by aesthetics i don't mean the code (goodness no :-) just the, um, tidiness of the set of functions/key mappings.) In any case, i'd like to summarize the functions i provided and, in case anyone is interested in using them, i'll post the mlisp in a separate message. First of all, early on it became clear that i ought to emphasize browsing (as opposed to mutative) functions for the mouse. The main reason for this was in the limitations of the protocols - events are produced only during the downstroke of single keys and no shifts are available. (However, it is possible to do other things, like determine the position of the cursor just after the event, which i used to advantage.) I assigned different functionalities to the three sun mouse buttons, qualified by the region of the Sun window the mouse inhabited (relative to the cursor). Generally, when the mouse is in the same window as the cursor, the action involves absolute positioning wrt the mouse position. Interactions with other windows happen when the mouse and cursor are in different windows during an event, and in two instances the echo line is used as a proportional-positioning (scroll bar) scale when the mouse inhabits it. What follows are the particulars (taken, for times sake, pretty much directly from the mlisp comments): - The left mouse button deals with marks. - The left mouse button sets an anonymous mark at the dot (gosmacs term for cursor position) if the mouse is not in the minibuffer (gosmacs term for the extended-command echo line); otherwise exchanges dot and mark. - The middle mouse button provides cursor positioning, within a window, between buffers, or throughout a buffer. - The middle moves the dot to the mouse if the mouse is within (or on the mode line of) a non-minibuffer buffer; the dot is moved across buffers if necessary (i.e. when the mouse and cursor are in different buffers). When the mouse is in the minibuffer the dot is moved to a position in the current buffer proportional to the position of the mouse on the minibuffer line (first and last character positions in the minibuffer line insured to map to the beginning and end of the buffer). - The right button provides window/buffer scrolling. - The right, when clicked in the same buffer as the cursor, moves the line containing the cursor to the selected line. If the mouse is in another (non-minibuffer) window then the cursor's buffer is swapped into that window and vice-versa (this provides a means for juggling the contents of windows on the screen). If clicked in the minibuffer the current buffer window is moved backward/forward a portion of a page proportional to the distance of the mouse from the minibuffers center, with full left going back and full right going forward a full page. (forward and reverse scrolling up to a page at a time).
manheime@nbs-amrf.UUCP (Ken Manheimer) (01/17/86)
> [Me, in prior (or subsequent, depending on the vagaries of > transmission) article:] > In any case, i'd like to summarize the functions i provided and, in > case anyone is interested in using them, i'll post the mlisp in a > separate message. The code of interest is 'new-mouse-filter'. <cut cut cut cut cut cut cut cut cut cut cut cut cut cut cut cut cut cut> ; ; Special key bindings for Sun Microsystems workstation console ; ; klm 7-Jun-85 Added scroll-region (mouse click in minibuffer) refinements ; klm 6-Jun-85 Made bounded-dot-to-x-y to circumvent mouse bug - mouse ; may put dot beyond end-of buffer ; klm 31-May-85 Adding function to move line containing dot to selected line ; (swapping buffers if necessary) and altered keypad bindings a little ; klm lost in obscurity Developed alternative "new-mouse-filter" ; function. (bind-to-key "new-mouse-filter" "\eM") ; ESC-M = mouse report-code prefix. (bind-to-key "describe-key" "\e[208z") ; keypad R1 (bind-to-key "line-to-top-of-window" "\e[209z") ; keypad R2 (bind-to-key "shell" "\e[210z") ; keypad R3 (bind-to-key "dot-to-left-margin" "\e[211z") ; keypad R4 (bind-to-key "dot-to-centre" "\e[212z") ; keypad R5 (bind-to-key "dot-to-right-margin" "\e[213z") ; keypad R6 (bind-to-key "scroll-one-line-down" "\e[214z") ; keypad R7 (bind-to-key "previous-line" "\e[A") ; keypad R8 (up-arrow) (bind-to-key "previous-page" "\e[216z") ; keypad R9 (bind-to-key "backward-character" "\e[D") ; keypad R10 (left-arrow) (bind-to-key "set-mark" "\e[218z") ; keypad R11 (bind-to-key "forward-character" "\e[C") ; keypad R12 (right-arrow) (bind-to-key "scroll-one-line-up" "\e[220z") ; keypad R13 (bind-to-key "next-line" "\e[B") ; keypad R14 (down-arrow) (bind-to-key "next-page" "\e[222z") ; keypad R15 (autoload "dot-to-left-margin" "shift.ml") (autoload "dot-to-right-margin" "shift.ml") (defun (bounded-dot-to-x-y (move-dot-to-x-y (arg 1 "X coordinate: ") (arg 2 "Y coordinate: ")) (if (> (dot) (buffer-size)) (end-of-file)) ) (new-mouse-filter button mouse-x mouse-y (setq button (get-tty-character)) (setq mouse-x (get-tty-character)) (setq mouse-y (get-tty-character)) ; (setq single-step (breakpoint)) ; uncomment this line for debugging (if (= button '1') ; left ; - The left mouse button sets an anonymous mark at the dot if the mouse is ; within a buffer, (i.e. not in minibuffer) otherwise exchanges dot and mark. (if (error-occurred (save-excursion (bounded-dot-to-x-y mouse-x mouse-y))) (exchange-dot-and-mark) (progn (set-mark) (message "Mark set.")) ) (= button '2') ; middle ; - The middle moves the dot to the mouse if the mouse is within (or on ; the mode line of) a non-minibuffer buffer; the dot is moved across buffers ; if necessary). If the mouse is in the minibuffer the dot is moved to a ; position in the current buffer proportional to the position of the ; mouse the minibuffer line (first and last character positions in the ; the minibuffer line insured to map to the beginning and end of the buffer). (if (error-occurred (bounded-dot-to-x-y mouse-x mouse-y)) (if (= mouse-x 1) (beginning-of-file) (= mouse-x (window-width)) (end-of-file) (goto-character ; the 100s are there for emacs integer math (/ (* (/ (* mouse-x 100) (window-width)) (buffer-size)) 100) ) ) ) (= button '3') ; right ; - The right, when clicked in the same buffer as the cursor, moves the ; line containing the cursor to the selected line. If the mouse is in ; another (non minibuffer) window then the cursor's buffer is swapped ; into the selected window and vice-versa. If clicked in the minibuffer the ; current buffer window is moved backward/forward a portion of a page ; proportional to the distance of the mouse from the minibuffers center, ; with full left going back and full right going forward a full page. (progn start-buffer start-dot swap-with-buffer distance (setq start-buffer (current-buffer-name)) (setq start-dot (dot)) (if (! (error-occurred (save-excursion (bounded-dot-to-x-y mouse-x mouse-y) (if (= start-buffer (setq swap-with-buffer (current-buffer-name))) (progn (setq swap-with-buffer "") (setq distance (line-distance start-dot (dot)) )))) )) ; do the selection scroll or swap (if (!= swap-with-buffer "") ; if switch is to be made... (progn (switch-to-buffer swap-with-buffer) (bounded-dot-to-x-y mouse-x mouse-y) (switch-to-buffer start-buffer)) (provide-prefix-argument distance (scroll-one-line-down))) ; do the proportional scroll (provide-prefix-argument ; 100s are for emacs integer math (* (- (/ (* (/ (* mouse-x 100) ; proportional position (window-width)) (window-height)) 100) (/ (window-height) 2)) ; midway in minibuffer 2) ; full scroll (scroll-one-line-up)) ) )) ) ) (novalue)
jr@bbncc5.UUCP (John Robinson) (01/21/86)
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 <TYPE> [nnnn [;nnnn]*] <COMM>. This format is used in both directions over the link. <TYPE> is the character [ for standard commands and the character : for private commands. <COMM> 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 : <CR> . 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}