Search code examples
canvasdartfullscreen

How to set and cancel fullscreen canvas in dart


The problem is the inconsistency between different browsers.

Running with dart chromium, js chrome, js opera

  1. enter and exit fullscreen works when double clicking

  2. m_oCanvas.width = (window.screen.width*0.75).toInt() causes a canvas that is centred and 75% of the width

  3. when exiting fullscreen with 'esc', HandleFSEvent gets called, document.fullscreenElement is correct (null, or canvas). the esc detection "m_bFullScreen && document.fullscreenElement==null" works.

Running as js in firefox, js in ie

  1. only enter fullscreen works by double clicking, not exit

  2. m_oCanvas.width = (window.screen.width*0.75).toInt() causes a zoomed in canvas that covers the entire screen.

  3. when exiting fullscreen with 'esc', HandleFSEvent does not get called. the esc detection "m_bFullScreen && document.fullscreenElement==null" does not work, since it sometimes cancel a wanted fullscreen.

So the question is how to make changing to/from fullscreen by double clicking, and from fullscreen by pressing esc working the same in all browsers.

main.dart:

library fullscreen_test;

import 'dart:html';
import 'dart:js';

void FullscreenWorkaround(CanvasElement canvas)
{
  var canv = new JsObject.fromBrowserObject(canvas);

  if (canv.hasProperty("requestFullscreen")) {
    canv.callMethod("requestFullscreen");
  }
  else {
    List<String> vendors = ['moz', 'webkit', 'ms', 'o'];
    for (String vendor in vendors) {
      String vendorFullscreen = "${vendor}RequestFullscreen";
      if (vendor == 'moz') {
        vendorFullscreen = "${vendor}RequestFullScreen";
      }
      if (canv.hasProperty(vendorFullscreen)) {
        canv.callMethod(vendorFullscreen);
        return;
      }
    }
  }
}
void ExitFullscreenWorkaround()
{
  var doc = new JsObject.fromBrowserObject(document);

  if (doc.hasProperty("exitFullscreen")) {
    doc.callMethod("exitFullscreen");
  } else if (doc.hasProperty("mozCancelFullScreen")) {
    doc.callMethod("mozCancelFullScreen");
  } else if (doc.hasProperty("webkitExitFullscreen")) {
    doc.callMethod("webkitExitFullscreen");
  } else if (doc.hasProperty("msExitFullscreen")) {
    doc.callMethod("msExitFullscreen");
  }
}

class C_GameHandler
{
  CanvasRenderingContext2D m_oContext;
  CanvasElement m_oCanvas;
  int _m_iOrginalCanvasW, _m_iOrginalCanvasH;

  C_GameHandler(CanvasElement canvas)
  {
    m_oCanvas = canvas;
    m_oContext = m_oCanvas.getContext("2d");
    _m_iOrginalCanvasW = m_oCanvas.width;
    _m_iOrginalCanvasH = m_oCanvas.height;
  }

  bool m_bFullScreen = false;
  void ToggleFullScreen()
  {
    m_bFullScreen = !m_bFullScreen;
    if(m_bFullScreen) {
      FullscreenWorkaround(m_oCanvas);
      m_oCanvas.width = (window.screen.width*0.75).toInt();
      m_oCanvas.height = (window.screen.height*0.75).toInt();
    } else {
      ExitFullscreenWorkaround();
      m_oCanvas.width = _m_iOrginalCanvasW;
      m_oCanvas.height = _m_iOrginalCanvasH;
    }
  }

  void HandleDClick(MouseEvent event)
  {
    ToggleFullScreen();
  }

  void HandleFSEvent(Event e)
  {
    //is unreliable, cant use
    if(document.fullscreenElement==null)
      print('onFullscreenChange off\n');
    else print('onFullscreenChange on\n');
  }

  bool Loop(double time)
  {
    //detect if user has canceled fullscreen (using esc)
    if( m_bFullScreen && document.fullscreenElement==null) {
      print('log 1.');
//      ExitFullscreenWorkaround();
      m_oCanvas.width = _m_iOrginalCanvasW;
      m_oCanvas.height = _m_iOrginalCanvasH;
      m_bFullScreen = false;
    }
    if(!m_bFullScreen && document.fullscreenElement==m_oCanvas) {
      print('log 2.');
    }

    //draw something
    m_oContext.fillStyle = "green";
    m_oContext.clearRect(0, 0, m_oCanvas.width, m_oCanvas.height);
    m_oContext.fillRect(m_oCanvas.width~/2, 0, 20, m_oCanvas.height);
    m_oContext.fillRect(0, m_oCanvas.height~/2, m_oCanvas.width, 20);

    // keep looping
    this._renderFrame();
    return true;
  }

  void Start()
  {
    window.onDoubleClick.listen(HandleDClick);
    document.onFullscreenChange.listen(HandleFSEvent);

    this._renderFrame();
  }

  void _renderFrame() {
    window.requestAnimationFrame((num time) { this.Loop(time); });
  }
}

void main()
{
  C_GameHandler oGame = new C_GameHandler(querySelector('#webplay-canvas'));
  oGame.Start();
}

Solution

  • I changed from fullscreen-switching to just fill the window instead, much because mobile browsers don't seem to support the fullscreen API yet/ever. It also solves the problem of scaling based on screen size.

    css

    * {
      margin:0; padding:0;
    }
    
    html, body {
      width:100%; height:100%;
      margin: 0px;
      border: 0;
      overflow: hidden; /*  Disable scrollbars */
    }
    
    #canvas {
      background-color: black;
      display: block;
    }
    

    code

    void ScreenSize()
    {
      double dScale = 1.0;
      if(window.innerWidth>900) dScale = 0.75;
      if(window.innerWidth>1400) dScale = 0.5;
      m_oCanvas.width  = (window.innerWidth*dScale).toInt();
      m_oCanvas.height = (window.innerHeight*dScale).toInt();
      m_oCanvas.style.width = (window.innerWidth-0).toInt().toString()+'px';
      m_oCanvas.style.height = (window.innerHeight-0).toInt().toString()+'px';
    
      _m_oGraph.Init(m_oCanvas); //apply the new size
    }
    
    void OnResize(Event e)
    {
      ScreenSize();
    }
    
    window.onResize.listen(OnResize);