Introduction

GLFW is an Open Source, multi-platform library that provides a simple API for creating windows, contexts, receiving input and events. The primary implementation focuses on the desktop platforms.

With the Web and the browser platform taking over, and new technologies like WebAssembly, there is a strong desire to be able to write or port applications to this new paradigm.

emscripten-glfw is an implementation of the GLFW API with the primary goal of implementing as many features as possible in the context of a web browser.

emscripten-glfw is now an Emscripten port, one that is easily available via the (emcc) option --use-port=contrib.glfw3.

To get a taste of how powerful this is, you can check out the demo which runs in any browser supporting OpenGL (all browsers should work). Or WebGPU Shader Toy, which runs in a Web Browser supporting WebGPU (Chrome or Edge as of this writing).

History

Emscripten has a GLFW built-in implementation. It was implemented back in 2013 in pure JavaScript. It currently states that it implements the 3.2.1 version of the API released in 2016 (as returned by glfwGetVersion). It is not well maintained and lacks support for more recent additions like the Gamepad API. It does not comply with the error handling paradigm of GLFW (glfwSetErrorCallback stores the function pointer but never uses it and some APIs throw an exception when called (like glfwGetTimerFrequency)).

After doing some work on this JavaScript implementation (adding Hi DPI/4K support), and adding contrib port support to Emscripten, it became clear to me that a clean slate approach to implementing GLFW3 was required (and suggested).

Fast-forward to today, and my implementation is not only available, but easily usable as an Emscripten port. It can easily be integrated in any application wanting to use GLFW in the browser.

Since ImGui v1.91.0, ImGui can be configured to use this port, allowing full gamepad and clipboard support amongst many other advantages.

Primary Features

For more details about these features, check the documentation. For a comparison with the built-in implementation, check the comparison page.

Multiple windows

In the context of the browser, a (GLFW) window is associated with an HTML canvas. emscripten-glfw supports any number of windows.

Example 1: the demo uses 2 windows

2 windows (demo)
The right canvas/window is resizable like a desktop window using the handle

Example 2: WebGPU Shader Toy uses 2 windows as well

2 windows (WebGPU Shader Toy)
Both windows are individually resizable via their respective handle
2 windows (WebGPU Shader Toy)
Or via the browser window
emscripten-glfw provides a convenient API to make the canvas resizable (emscripten::glfw3::MakeCanvasResizable)

Mouse and keyboard

The library fully supports the mouse and keyboard, including sticky button behavior (resp. sticky key behavior).

In addition, when the mouse is being held, and it moves outside the browser window, it continues to work, thus making moving a scrollbar natural and uninterrupted.

Mouse works outside the browser
Moving the scrollbar when the mouse is outside the browser

Gamepad support

emscripten-glfw implements the full Gamepad API, thus making dealing with joysticks consistent across platforms.

The Gamepad
The standard gamepad

Fullscreen and Hi DPI

The library has full support for fullscreen (with resizing when requested) and Hi DPI for 4K displays. Both features are demonstrated in this example (using Ctrl + H to toggle between Hi DPI and Low DPI, and Ctrl + F to go fullscreen).

Clipboard - Copy/Paste

Dealing with the outside clipboard is a bit tricky in a browser environment due to security reasons. This implementation supports both copy and paste with the desktop clipboard as long as the proper shortcuts are being used.

Copy/Paste
Copy/Paste with an external application (left is WebGPU Shader Toy / right is TextMate)

Other Features

In addition to the previous features listed above, emscripten-glfw implements a host of other functionalities, not implemented by the built-in implementation:

  • Cursors (all GLFW cursors are supported)
  • Window size constraints (size limits and aspect ratio)
  • Window opacity
  • Window status (Focused / Hovered / Position)
  • Timer
  • Error handling

Give it a try

This has been a very fun project to work on. I hope this introduction has been helpful. Feel free to give it a try for yourself and provide feedback or questions in the GitHub project issues tracker.

If you want to integrate in your project, Emscripten offers a straightforward and convenient syntax:

emcc --use-port=contrib.glfw3 main.cpp -o /tmp/index.js

You can follow news and announcements on the pongasoft website (also available as an RSS feed).