getGraphicsEvent 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,
                 onIdle = NULL,
                 consolePrompt = prompt)
setGraphicsEventHandlers(which = dev.cur(), ...)
getGraphicsEventEnv(which = dev.cur())
setGraphicsEventEnv(which = dev.cur(), env)

Arguments

prompt

prompt to be displayed to the user in the graphics window

onMouseDown

a function to respond to mouse clicks

onMouseMove

a function to respond to mouse movement

onMouseUp

a function to respond to mouse button releases

onKeybd

a function to respond to key presses

onIdle

a function to call when no events are pending

consolePrompt

prompt to be displayed to the user in the console

which

which graphics device does the call apply to?

...

items including handlers to be placed in the event environment

env

an environment to be used as the event environment

Details

These functions allow user input from some graphics devices (currently only the windows(), X11(type = "Xlib") and X11(type = "cairo") 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 six arguments to getGraphicsEvent are given, then it uses those in a call to 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 setGraphicsEventHandlers or setGraphicsEventEnv on one or more graphics devices, and then use getGraphicsEvent() with no arguments to retrieve event data. getGraphicsEventEnv() may be used to save the event environment for use later.

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

The mouse event handlers should be functions with header function(buttons, x, y). The coordinates x and y will be passed to mouse event handlers in device independent coordinates (i.e., the lower left corner of the window is (0,0), the upper right is (1,1)). The 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 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 shift-a will be passed as "A". The following special keys may also be passed to the handler:

  • Control keys, passed as "Ctrl-A", etc.

  • Navigation keys, passed as one of
    "Left", "Up", "Right", "Down", "PgUp", "PgDn", "End", "Home"

  • Edit keys, passed as one of "Ins", "Del"

  • Function keys, passed as one of "F1", "F2", ...

The idle event handler onIdle should be a function with no arguments. If the function is undefined or NULL, then R will typically call a system function which (efficiently) waits for the next event to appear on a filehandle. Otherwise, the idle event handler will be called whenever the event queue of the graphics device was found to be empty, i.e. in an infinite loop. This feature is intended to allow animations to respond to user input, and could be CPU-intensive. Currently, onIdle is only implemented for X11() devices.

Note that calling Sys.sleep() is not recommended within an idle handler - Sys.sleep() removes pending graphics events in order to allow users to move, close, or resize windows while it is executing. Events such as mouse and keyboard events occurring during Sys.sleep() are lost, and currently do not trigger the event handlers registered via getGraphicsEvent or setGraphicsEventHandlers.

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

  • one of the event handlers returns a non-NULL value which will be returned as the value of getGraphicsEvent, or

  • the user interrupts the function from the console.

Value

When run interactively, getGraphicsEvent returns a non-NULL value returned from one of the event handlers. In a non-interactive session, getGraphicsEvent will return NULL immediately. It will also return NULL if the user closes the last window that has graphics handlers.

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

setGraphicsEventEnv and setGraphicsEventHandlers return the previous event environment for the graphics device.

Author(s)

Duncan Murdoch

Examples

# This currently only works on the Windows, X11(type = "Xlib"), and
# X11(type = "cairo") screen devices...
## Not run: 
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)

## End(Not run)

Copyright (©) 1999–2012 R Foundation for Statistical Computing.
Licensed under the GNU General Public License.