Skip to content

Problems caused by dev.off() behaviour

6 messages · Trevor Davis, Duncan Murdoch, Avi Gross

#
I found some weird behaviour and reported it as
https://bugs.r-project.org/show_bug.cgi?id=18604 and
https://github.com/yihui/knitr/issues/2297, but it turns out it was user 
error.

The dev.off() function was behaving as documented, but it behaves in an 
unexpected (by me) way, and that caused the "bugs".

The issue is that

    dev.off()

doesn't always result in the previous graphics device being made 
current.  If there are two or more other open graphics devices, it won't 
choose the previous one, it will choose the next one.

I'm letting people know because this might affect other people too.  If 
you use dev.off(), don't assume it restores the previous device!

Here's my little workaround alternative:

   safe.dev.off  <- function(which = dev.cur(), prev = dev.prev()) {
     force(prev)
     dev.off(which)
     dev.set(prev)
   }

Use it just like dev.off(), but it *will* restore the previous device.

Duncan Murdoch
#
I'm observing that if there were no previously open graphics devices then
your `safe.dev.off()` opens up a new graphics device which may be an
undesired side effect (because "surprisingly" `dev.set()` on the null
graphics device opens up a new graphics device).  To avoid that you could
check if `dev.list()` is greater than length 1L:

   safe.dev.off  <- function(which = dev.cur(), prev = dev.prev()) {
     force(prev)
     dev.off(which)
     if (length(dev.list()) > 1L) {
       dev.set(prev)
     }
   }

Trevor

On Mon, Oct 2, 2023 at 11:54?AM Duncan Murdoch <murdoch.duncan at gmail.com>
wrote:

  
  
#
Thanks!  However, isn't length(dev.list()) == 0 when there are no 
devices?  That's what I'm seeing on MacOS.

Duncan Murdoch
On 02/10/2023 4:21 p.m., Trevor Davis wrote:
#
devices?  That's what I'm seeing on MacOS.

If there is only one graphics device then R should automatically set it as
the active graphics device so it isn't really necessary to manually set
it.  Although there wouldn't be any harm in manually setting it you only
really need to worry about setting the previous graphics device when there
are two or more devices open.

Trevor

On Mon, Oct 2, 2023 at 5:25?PM Duncan Murdoch <murdoch.duncan at gmail.com>
wrote:

  
  
#
On 02/10/2023 10:17 p.m., Trevor Davis wrote:
Right, I see.  With some more fiddling, I've decided that I don't like 
the error you get if you try to close device 1, so here's the current 
version:

safe.dev.off  <- function(which = dev.cur(), prev = dev.prev()) {
   if (which != 1) {
     force(prev)
     grDevices::dev.off(which)
   }
   if (length(dev.list()))
     dev.set(prev)
   else
     c("null device" = 1)
}

This does the dev.set even if there's only one device so it can return 
the resulting device number.

Duncan Murdoch
#
Just pointing out that if you do not want to SEE an error message that is
otherwise harmless, one option in R is to let the error happen but arrange
to deal with it in some way including just suppressing the message.

On Tue, Oct 3, 2023, 5:27 AM Duncan Murdoch <murdoch.duncan at gmail.com>
wrote: