true full screen in Processing.js, 2015

The new improved 2015 Full Screen Demo starts Full Browser Window and goes Full Screen. Instead of the canvas being one big toggle switch, there’s now a context-sensitive button on the lower right. The button disappears when the mouse has been inactive.

The nuts and bolts of the Fullscreen API now reside in a script on the HTML page. The Processing sketch still manages button visibility, but getting all that fullscreen-related Javascript out of there makes the sketch a lot cleaner.

If you want the canvas to be one big toggle switch, there’s always the 2014 version.

With Windows 8 and XP running on a Mac using VMware Fusion 5, I tested both versions on various up-to-date browsers. They work in the following:

OS X Mavericks: Safari, Chrome, Firefox, and Opera (though if you use the 1.4.8 version of Processing.js it doesn't work in Opera on the Mac, which is why I use 1.4.1).

Windows 8: Internet Explorer 11, Chrome, Firefox, and Opera (the 2015 approach even works in the old Opera 12, which the 2014 one sorta does, except it doesn't recognize the Escape key.)

Windows XP: Chrome, Firefox, and Opera (same as in Windows 8), but not IE 8, which doesn't support the canvas tag.

Here's the HTML for the 2015 version:

<!DOCTYPE html>
<html>
<head>
<title>Processing.js Full Screen demo 2015</title>
<style type="text/css">
  body {margin:0; padding:0;} /* remove top and left whitespace */
  canvas {display:block; position:fixed; top:0px; left:0px; bottom:0px; right:0px;} 
  canvas:focus {outline:0;} /* remove blue outline around canvas */
  .fs {position:fixed; right:50px; bottom:50px; font-size: 200%;}
  #enter {display:block;}
  #exit {display:none;}
</style>  
<script src="../processing-1.4.1.min.js"></script>
</head>
<body>
<canvas id="canv" data-processing-sources="pjsfullscreendemo.pde">
<h1>(There would be some art here if your web browser
supported the HTML5 canvas tag.)</h1>
</canvas>
<button id="enter" class="fs" onclick="goFullScreen();">View Full Screen</button>
<button id="exit" class="fs" onclick="exitFullScreen();">Exit Full Screen</button>

<script type="application/javascript">
var viewfs = document.getElementById("enter");
var exitfs = document.getElementById("exit");
var processingInstance;
var fullscreen = false;

window.onresize=function(){setSketchSize()};
function setSketchSize() {
  if (!processingInstance) {
    processingInstance = Processing.getInstanceById("canv");
  } 
  // call Processing size() function over in the sketch
  processingInstance.size(document.documentElement.clientWidth,document.documentElement.clientHeight);  
}

document.addEventListener("fullscreenchange", setFullscreenBooleanInSketch);
document.addEventListener("webkitfullscreenchange", setFullscreenBooleanInSketch);
document.addEventListener("mozfullscreenchange", setFullscreenBooleanInSketch);
document.addEventListener("MSFullscreenChange", setFullscreenBooleanInSketch);

function setFullscreenBooleanInSketch() {
  if (document.fullscreenElement || 
      document.mozFullScreenElement || 
      document.webkitFullscreenElement || 
      document.msFullscreenElement) { // if fullscreen
    viewfs.style.display = "none";
    exitfs.style.display = "block";
    fullscreen = true;      
  } else {
    viewfs.style.display = "block";
    exitfs.style.display = "none";
    fullscreen = false;
  }
  if (!processingInstance) {
    processingInstance = Processing.getInstanceById("canv");
  } 
  // sets the value of the boolean 'fullscreen' over in the sketch
  processingInstance.setFullscreen(fullscreen);  
}

function goFullScreen() {
  if (document.fullscreenEnabled || 
      document.webkitFullscreenEnabled || 
      document.msFullscreenEnabled ||
      document.mozFullScreenEnabled) {  
    if (!document.fullscreenElement && 
        !document.mozFullScreenElement && 
        !document.webkitFullscreenElement && 
        !document.msFullscreenElement) { 
      if (document.documentElement.requestFullscreen) {
        document.documentElement.requestFullscreen();
      } else if (document.documentElement.mozRequestFullScreen) {
        document.documentElement.mozRequestFullScreen();
      } else if (document.documentElement.webkitRequestFullscreen) {
        document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
      } else if (document.documentElement.msRequestFullscreen) {
        document.documentElement.msRequestFullscreen();
      }
    } 
  }
} 

function exitFullScreen() {
  if ((document.fullscreenEnabled || 
       document.webkitFullscreenEnabled || 
       document.msFullscreenEnabled ||
       document.mozFullScreenEnabled)) {  
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    }
  }
} 
</script>
</body>
</html>

Here's the sketch, now with 97% less Javascript:

// globals needed for resizing canvas, hiding buttons
var viewfs = document.getElementById("enter");
var exitfs = document.getElementById("exit");
boolean fullscreen = false;
boolean showing = true;
boolean justoff = false;
int mouseWaitress;

// specific to this sketch's art code...
float y, yinterval, ystart, yend, xint, xstart, xend;
int hue, brimin, brimax, stromin, stromax;

void setup() {
  size(document.documentElement.clientWidth, document.documentElement.clientHeight);
  mouseWaitress = millis() + 10000; 
  // this sketch only...
  yend = 0; y=-1.0;  
  colorMode(HSB);
  background(0);
}

void draw() {
  // begin art code
  if (y<yend) {
    yinterval = height*random(0.02,0.025); xint = int(width/random(40,180));
    hue = int(random(135)); brimin = int(random(225)); brimax = brimin + 30; 
    stromin = int(random(1,5)); stromax = stromin*8; 
    float xs = 0; int r = int(random(3)); if (r<2) {xs = random(width);}
    float xe = width; r = int(random(3)); if (r<2) {xe = random(width);}
    xstart = min(xs, xe); xend = max(xs, xe);
    float ys = 0; r = int(random(3)); if (r<2) {ys = random(height);}
    float ye = height; r = int(random(3)); if (r<2) {ye = random(height);}
    ystart = max(ys, ye); yend = min(ys, ye); y=ystart; 
  }
  stroke(hue+int(random(20)), 100+int(random(155)), int(random(brimin,brimax))); 
  for (float x=xstart; x<xend; x+=xint) {
    strokeWeight(int(random(stromin, stromax))); strokeCap(ROUND);
    line(x+random(-xint,xint), y+random(-xint,xint), x+random(-xint,xint), y+random(-xint,xint));
  }
  y-=(yinterval);
  // end art code

  // Show mouse pointer and View/Exit button when mouse is moved.
  // Hide them 10 seconds after page loads, or 2 seconds after last  
  // mouse movement or window resize. 
  int currtime = millis();
  if ((mouseX != pmouseX) || (mouseY != pmouseY)) { // if mouse moved,
    if (!showing && !justoff) { // and if they're hidden,
      cursor(); showing = true; // show pointer and relevant image
      if (fullscreen) { 
        exitfs.style.display = "block";
      } else {
         viewfs.style.display = "block";
      }
    }
    justoff = false; // kludge so hovered-over button doesn't pop back on
    if (mouseWaitress < currtime + 2000) { // if not in first 10 seconds,
      mouseWaitress = currtime + 2000; // hide stuff 2 seconds from now
    }
  } else { // mouse has not moved
    if (showing) {
      if (currtime > mouseWaitress) { // they've been visible long enough,
        noCursor(); showing = false; // hide pointer and images
        viewfs.style.display = "none";
        exitfs.style.display = "none";
        justoff = true;
      }
    }
  }
}

// Called when the screen resizes, this lets the script on the HTML page
// change the value of the boolean 'fullscreen' here in the sketch...
void setFullscreen(boolean whatItIs) {
  fullscreen = whatItIs; // needed
  cursor(); showing = true; // needed housekeeping after resize
  mouseWaitress = millis() + 2000; // recommended, duration can vary 
  background(0); // optional, but the sketch WILL blank out on resize
}

There are some examples of full screen art on my web site that use this approach.

Tagged:

Comments

  • edited February 2014

    Really nice to see a sketch go full screen! That's something I can't do even on the IDE, as full screen does not work on Java+Ubuntu. But it does with your technique.

    Thanks for sharing! :)

  • @hamoid, so boolean sketchFullScreen() { return true; } does not work in Ubuntu? Present mode doesn't work?

  • I'm currently using Lubuntu 13.04 and boolean sketchFullScreen() { return true; } works alright!

  • edited March 2014

    @mcspud unfortunately it doesn't, and I don't remember it ever working.

    Screenshot from 2014-03-11 10:47:18

    The top menu and left side buttons that the operating system provides are always there. Which is a funny thing, because lots of programs in Ubuntu, even very basic ones, allow true full screen (the image viewer eog, firefox, chromium, the gedit and SciTE text editors, myPaint).

    I think the reason is explained here. Someone mentions a workaround, but it does not work for me.

    I suspect it's Unity's fault, and with other window managers, like the one provided in Lubuntu, it works. I should install http://ubuntustudio.org/ already...

  • edited July 2014

    @hamoid Try using the P2D instead of the default java2D

    size(displayWidth, displayHeight, P2D);

    This completely works with gnome, and it sometimes works with unity (ubuntu 12.04). Also, to get rid of the buttons without present mode, you can do this in setup

    frame.removeNotify();
    frame.setUndecorated(true);
    frame.addNotify();
    

    You can also move the window around with

    frame.setLocation(x, y);

  • Thanks, but unfortunately I see no improvement. I'm on 14.04 now. I know that in non-unity system it works fine.

  • I'm using 14.04 and setting the frame undecorated AND resizable makes it work even with unity.

    public void init () {
            frame.removeNotify();
            frame.setUndecorated( true );
            frame.setResizable( true );
            frame.addNotify();
            super.init();
        }
    
  • @mrzl I think my Unity is tougher than yours :P

    With your code, it covers everything except the top bar with the date/time...

    Some people can't use external monitor, others can't do full screen ;)

  • Thank you, with the help of your code I was able to get a undistorted app (drawing) on the whole canvas. The only thing I had to add was:

    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    

    However, That's quite a lot of code just to get a fullsize app..

  • Glad it helped. I'm sure this isn't the most compact, complete, or elegant solution possible. I don't use mobile devices myself, so it wasn't tested with any of those.

    Thanks for sharing your findings about iOS.

  • @hamoid: Haha! Actually I remember that it was only working when using Processing as a library from IntelliJ- when using the Processing IDE it wasn't working either.. Duh..

  • @mrzl I solved the problem. Got rid of the unities ;) In Arch Linux it works fine.

Sign In or Register to comment.