[net.emacs] emacs mouse support

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}