don@BRILLIG.UMD.EDU (Don Hopkins) (03/20/88)
Here's a little NeWS "desk accessory" I wrote to make a graphical
mouse in a window whose movement tracks the real mouse's movement
around the screen. It leaves behind a trail where you move, and spots
where you press buttons. The buttons light up when you press them, and
it leaves a thick trail behind when you drag with a button down. I
find it useful for making screen dumps and demonstrating how to
operate the mouse. It's a neat way to show where heavy mouse traffic
happens over a long period of time. It also works nicely with
journalling!
This is but a first cut -- I plan to add more features (of course!).
I want to make a remote MouSee, so you can see other people's mice
over the network, and even grab them, move them around, and press
their buttons for them! (Aww, c'mon! I can think of a /few/ legitimate
uses for it!)
-Don
====Cut here: 8X========================================================
%!
%
% MouSee.ps
% By Don Hopkins, University of Maryland Human Computer Interaction Lab.
%
% MouSee run.
% MouSee Spot make, You Button press when.
% MouSee Trail leave, You Mouse move when.
% MouSee Trail thick leave, You Button press Mouse move and when.
% Fun have!
%
% Copyright (C) 1988 by Don Hopkins. All rights reserved.
% This program is provided for unrestricted use, provided that this
% copyright message is preserved. There is no warranty, and no author
% or distributer accepts responsibility for any damage caused by this
% program.
%
/MouSeeWindow DefaultWindow
dictbegin
/MouseWidth 38 def
/MouseHeight 50 def
/MouseX 0 def
/MouseY 0 def
/OldMouseX 0 def
/OldMouseY 0 def
/CornerRadius 4 def
/HScale null def
/VScale null def
/LeftButtonState false def
/MiddleButtonState false def
/RightButtonState false def
/ButtonRadius 3 def
/ButtonWidth .1 def
/MouseCanvas null def
dictend
classbegin
/PaintClient {
gsave
1 fillcanvas
draw-mouse
grestore
} def
/reshape { % x y w h => -
/reshape super send
gsave
framebuffer setcanvas
clippath pathbbox 4 -2 roll pop pop % fbw fbh
ClientCanvas setcanvas
clippath pathbbox 4 -2 roll pop pop % fbw fbh ccw cch
MouseHeight sub 1 max exch
MouseWidth sub 1 max exch
3 -1 roll div /VScale exch def
exch div /HScale exch def
grestore
} def
/mouse-path {
CornerRadius 0 0 MouseWidth MouseHeight rrectpath
} def
/mouse-trail {
DX DY rlineto
} def
/move-mouse { % x y => -
gsave
/OldMouseX MouseX def /OldMouseY MouseY def
/MouseY exch def /MouseX exch def
/DX MouseX OldMouseX sub HScale mul def
/DY MouseY OldMouseY sub VScale mul def
ClientCanvas setcanvas
((%, %) ) [MouseX MouseY] sprintf
dup stringbbox 8 add rectpath 1 setgray fill
0 0 moveto
0 setgray show
OldMouseX HScale mul
OldMouseY VScale mul translate
% mouse-path
% gsave 1 setgray fill grestore
% 1 setgray fill
MouseWidth 2 div MouseHeight 2 div moveto mouse-trail
% MouseWidth 0 moveto mouse-trail
% MouseWidth MouseHeight moveto mouse-trail
% 0 MouseHeight moveto mouse-trail
0 setlinecap
LeftButtonState MiddleButtonState RightButtonState
or or 4 1 ifelse
gsave dup 2 add setlinewidth 1 setgray stroke grestore
setlinewidth 0 setgray stroke
MouseCanvas setcanvas
MouseX HScale mul MouseY 3 sub VScale mul
movecanvas
grestore
} def
/draw-mouse {
gsave
MouseCanvas setcanvas
mouse-path
gsave .5 setgray fill grestore
0 setgray 3 setlinewidth stroke
draw-buttons
grestore
} def
/draw-buttons {
LeftButtonState draw-left-button
MiddleButtonState draw-middle-button
RightButtonState draw-right-button
} def
/draw-left-button {
MouseWidth .2 mul draw-button
} def
/draw-middle-button {
MouseWidth .5 mul draw-button
} def
/draw-right-button {
MouseWidth .8 mul draw-button
} def
/mark-button {
gsave
framebuffer setcanvas
XLocation HScale mul MouseWidth 2 div add
YLocation VScale mul MouseHeight 2 div add
ClientCanvas setcanvas
2 copy 10 0 360 arc 1 setgray fill
8 0 360 arc 0 setgray fill
grestore
} def
/set-left-button {
mark-button
/DownTransition eq
dup /LeftButtonState exch def
draw-left-button
} def
/set-middle-button {
mark-button
/DownTransition eq
dup /MiddleButtonState exch def
draw-middle-button
} def
/set-right-button {
mark-button
/DownTransition eq
dup /RightButtonState exch def
draw-right-button
} def
/draw-button { % bool x => -
gsave
MouseCanvas setcanvas
ButtonRadius exch
MouseWidth ButtonWidth mul sub MouseHeight .5 mul round
MouseWidth ButtonWidth mul dup add MouseHeight .4 mul round
rrectpath
gsave .25 .75 ifelse setgray fill grestore
1 setlinewidth 1 setgray stroke
grestore
} def
/update-mouse {
XLocation YLocation move-mouse
} def
/make-mouse {
gsave
/MouseCanvas ClientCanvas newcanvas def
MouseCanvas /Transparent false put
MouseCanvas /Retained true put
ClientCanvas setcanvas
mouse-path MouseCanvas
reshapecanvas
framebuffer setcanvas
currentcursorlocation
/MouseY exch def
/MouseX exch def
MouseCanvas setcanvas
MouseX HScale mul MouseY VScale mul movecanvas
MouseCanvas /Mapped true put
grestore
} def
/tracker {
createevent dup begin
/Name [
/LeftMouseButton /MiddleMouseButton /RightMouseButton
/MouseDragged
] def
/Priority 10 def
/Exclusivity true def
end expressinterest
createevent dup begin
/Name /Damaged def
/Canvas MouseCanvas def
end expressinterest
framebuffer setcanvas
{ awaitevent dup begin
Name {
/LeftMouseButton { Action set-left-button }
/MiddleMouseButton { Action set-middle-button }
/RightMouseButton { Action set-right-button }
/MouseDragged { update-mouse }
/Damaged { draw-mouse }
} case
redistributeevent
end
} loop
} def
/track {
make-mouse
/TrackProcess {tracker} fork def
} def
classend def
/win framebuffer /new MouSeeWindow send def
/reshapefromuser win send
/map win send
/track win send