% File src/library/grDevices/man/getGraphicsEvent.Rd
% Part of the R package, https://www.R-project.org
% Copyright 1995-2014 R Core Team
% Distributed under GPL 2 or later

\name{getGraphicsEvent}
\alias{getGraphicsEvent}
\alias{setGraphicsEventHandlers}
\alias{getGraphicsEventEnv}
\alias{setGraphicsEventEnv}
\title{Wait for a mouse or keyboard event from a graphics window}
\description{
This function waits for input from a graphics window in the
form of a mouse or keyboard event.
}
\usage{
getGraphicsEvent(prompt = "Waiting for input",
                 onMouseDown = NULL, onMouseMove = NULL,
                 onMouseUp = NULL, onKeybd = NULL,
                 consolePrompt = prompt)
setGraphicsEventHandlers(which = dev.cur(), ...)
getGraphicsEventEnv(which = dev.cur())
setGraphicsEventEnv(which = dev.cur(), env)

}
\arguments{
  \item{prompt}{prompt to be displayed to the user in the graphics window}
  \item{onMouseDown}{a function to respond to mouse clicks}
  \item{onMouseMove}{a function to respond to mouse movement}
  \item{onMouseUp}{a function to respond to mouse button releases}
  \item{onKeybd}{a function to respond to key presses}
  \item{consolePrompt}{prompt to be displayed to the user in the console}
  \item{which}{which graphics device does the call apply to?}
  \item{...}{items including handlers to be placed in the event environment}
  \item{env}{an environment to be used as the event environment}
}
\details{
These functions allow user input from some graphics devices (currently
only the \code{windows()} and \code{X11(type = "Xlib")} screen displays
in base \R{}). Event handlers may be installed to respond to events
involving the mouse or keyboard.

The functions are related as follows.  If any of the first five
arguments to \code{getGraphicsEvent} are given, then it uses those
in a call to \code{setGraphicsEventHandlers} to replace any existing
handlers in the current device.  This is for compatibility with pre-2.12.0 \R{}
versions.  The current normal way to set up event handlers is to
set them using \code{setGraphicsEventHandlers} or \code{setGraphicsEventEnv} on
one or more graphics devices, and then use \code{getGraphicsEvent()} with
no arguments to retrieve event data.
\code{getGraphicsEventEnv()} may be used to save the event environment
for use later.

The names of the arguments in \code{getGraphicsEvent} are special.  When
handling events, the graphics system will look through the event
environment for functions named \code{onMouseDown}, \code{onMouseMove}, \code{onMouseUp}
and \code{onKeybd} and use them as event handlers.  It will use
\code{prompt} for a label on the graphics device.  Two other special names are
\code{which}, which will identify the graphics device, and
\code{result}, where the result of the last event
handler will be stored before being returned by \code{getGraphicsEvent()}.

The mouse event handlers should be functions with header
\code{function(buttons, x, y)}.  The coordinates \code{x}
and \code{y} will be passed to mouse event handlers in device independent
coordinates (i.e., the lower left corner of the window is \code{(0,0)},
the upper right is \code{(1,1)}).  The \code{buttons} argument
will be a vector listing the buttons
that are pressed at the time of the event, with 0 for left, 1 for middle, and 2
for right.

The keyboard event handler should be a function with header
\code{function(key)}.  A single element character vector will be passed
to this handler, corresponding to the key press.  Shift and other modifier
keys will have been processed, so \code{shift-a} will be passed as
\code{"A"}.  The following special keys may also be passed to the handler:
\itemize{
     \item Control keys, passed as \code{"Ctrl-A"}, etc.
     \item Navigation keys, passed as one of\cr
     \code{"Left", "Up", "Right", "Down", "PgUp", "PgDn", "End", "Home"}
     \item Edit keys, passed as one of \code{"Ins", "Del"}
     \item Function keys, passed as one of \code{"F1", "F2", ...}
}

The event handlers are standard R functions, and will be executed as though called
from the event environment.

In an interactive session, events will be processed until
\itemize{
     \item one of the event handlers returns
a non-\code{NULL} value which will be returned as the value of
\code{getGraphicsEvent}, or
      \item the user interrupts the function from the
console.
}
}
\value{
When run interactively,
\code{getGraphicsEvent} returns a non-\code{NULL} value returned from one of the event handlers.
In a non-interactive session, \code{getGraphicsEvent} will return \code{NULL} immediately.  It
will also return \code{NULL} if the user closes the last window that has graphics handlers.

\code{getGraphicsEventEnv} returns the current event environment for the graphics device,
or \code{NULL} if none has been set.

\code{setGraphicsEventEnv} and \code{setGraphicsEventHandlers} return the previous
event environment for the graphics device.
}
\author{Duncan Murdoch}
\examples{
# This currently only works on the Windows
# and X11(type = "Xlib") screen devices...
\dontrun{
savepar <- par(ask = FALSE)
dragplot <- function(..., xlim = NULL, ylim = NULL, xaxs = "r", yaxs = "r") {
    plot(..., xlim = xlim, ylim = ylim, xaxs = xaxs, yaxs = yaxs)
    startx <- NULL
    starty <- NULL
    prevx <- NULL
    prevy <- NULL
    usr <- NULL

    devset <- function()
        if (dev.cur() != eventEnv$which) dev.set(eventEnv$which)

    dragmousedown <- function(buttons, x, y) {
        startx <<- x
        starty <<- y
        prevx <<- 0
        prevy <<- 0
        devset()
        usr <<- par("usr")
        eventEnv$onMouseMove <- dragmousemove
        NULL
    }

    dragmousemove <- function(buttons, x, y) {
        devset()
        deltax <- diff(grconvertX(c(startx, x), "ndc", "user"))
        deltay <- diff(grconvertY(c(starty, y), "ndc", "user"))
	if (abs(deltax-prevx) + abs(deltay-prevy) > 0) {
	    plot(..., xlim = usr[1:2]-deltax, xaxs = "i",
		      ylim = usr[3:4]-deltay, yaxs = "i")
	    prevx <<- deltax
	    prevy <<- deltay
	}
        NULL
    }

    mouseup <- function(buttons, x, y) {
    	eventEnv$onMouseMove <- NULL
    }	

    keydown <- function(key) {
        if (key == "q") return(invisible(1))
        eventEnv$onMouseMove <- NULL
        NULL
    }

    setGraphicsEventHandlers(prompt = "Click and drag, hit q to quit",
                     onMouseDown = dragmousedown,
                     onMouseUp = mouseup,
                     onKeybd = keydown)
    eventEnv <- getGraphicsEventEnv()
}

dragplot(rnorm(1000), rnorm(1000))
getGraphicsEvent()
par(savepar)
}
}
\keyword{iplot}
