Skip to content

Window Management and Fullscreen

JamJar provides a system to manage the 'window', resizing the canvas, and dealing with full screen requests.

The WindowSystem manages the window.

Setting up the Window System

To set up a WindowSystem, you need to provide a message bus, the SDL window to manage, and the ID of the 'wrapper' HTML element that the canvas is contained in.

#include "window.hpp"
#include "standard/window/window_system.hpp"

...

auto window = JamJar::GetWindow("Fullscreen");

...

new JamJar::Standard::WindowSystem(messageBus, window, "canvas-wrapper");

This sets up the WindowSystem to manage the window, pointing to the canvas wrapper with the ID canvas-wrapper.

The WindowSystem can take in a set of optional properties to set things such as aspect ratio, max resolution, and if the system cursor should be shown.

// Using a 4/3 resolution
new JamJar::Standard::WindowSystem(messageBus, window, "canvas-wrapper", JamJar::Standard::WindowSystemProperties({
    .aspectRatio = 4/3
}));
// Using a 4/3 resolution with a max resolution of 400x300
new JamJar::Standard::WindowSystem(messageBus, window, "canvas-wrapper", JamJar::Standard::WindowSystemProperties({
    .aspectRatio = 4/3,
    .maxResolutionX = 400,
    .maxResolutionY = 300
}));
// Using a 4/3 resolution with a max resolution of 400x300 with a hidden cursor
new JamJar::Standard::WindowSystem(messageBus, window, "canvas-wrapper", JamJar::Standard::WindowSystemProperties({
    .aspectRatio = 4/3,
    .maxResolutionX = 400,
    .maxResolutionY = 300,
    .showCursor = false
}));

Canvas Wrapper

The canvas wrapper is an HTML element that the canvas is in, this is the HTML element that is used for adjusting the resolution of the canvas. The WindowSystem looks at the width and height of the canvas element as the maximum width and height that it should scale the canvas to. This is to allow the site to integrate the game and its canvas into the site easily, with scaling decisions made in HTML and CSS and stopping sites having to directly modify the canvas (which can be tricky and mess up games easily).

For example:

<style>
    #canvas-wrapper {
        display: flex;
        margin: auto;
        width: 100%;
        height: 100%;
        flex-direction: column;
        justify-content: center;
        flex-grow: 1;
    }

    #canvas {
        margin: auto;
        cursor: none;
        touch-action: none;
    }
</style>
<div id="canvas-wrapper">
    <canvas id="canvas"></canvas>
</div>

This is a typical set up, with the canvas wrapper configured to fit in to the site, with not much configuration required of the canvas element itself.

Resizing

The WindowSystem will listen out for any changes to the size of the browser window or full screen requests and automatically resize using screen size, canvas size, aspect ratio, and maximum resolution.

The aspect ratio and maximum resolution can be adjusted by sending messages that the WindowSystem will listen for.

Aspect Ratio

The aspect ratio is the aspect ratio that the canvas will adhere to, the WindowSystem will try and set the canvas resolution to the highest possible that fits the aspect ratio provided.

The aspect ratio can be set at runtime with a message.

#include "standard/window/window_system.hpp"
#include "message/message_payload.hpp"

...

messageBus->Publish(new JamJar::MessagePayload<double>(JamJar::Standard::WindowSystem::MESSAGE_SET_ASPECT_RATIO, 4/3););

This sets the aspect ratio to 4/3.

Maximum Resolution

The maximum resolution is a hard limit on the maxmimum resolution the WindowSystem will allow, it defaults to x: -1, y: -1 with -1 meaning no maximum is set.

An example of how the final resolution is calculated when using a maximum resolution:

  • Screen size: 1920×1080
  • Aspect ratio: 4x3
  • Maximum resolution: 1000x1000

Calculate the maximum size that fits in the maximum resolution: x = 1000, y = 1000 * (1/(4/3)) = 750.

Final resolution: 1000x750

The maximum resolution can be set at runtime with a message.

#include "standard/window/window_system.hpp"
#include "message/message_payload.hpp"

...

messageBus->Publish(new JamJar::MessagePayload<std::pair<int, int>>(
    JamJar::Standard::WindowSystem::MESSAGE_SET_MAX_RESOLUTION, std::pair<int, int>(400, 300)));

This sets the maximum resolution to 400x300.

System Cursor

You can choose to hide or show the system cursor. By default this is hidden. You can set this value by providing a WindowSystemProperties when initializing the WindowSystem.

At runtime you can choose to show or hide the cursor by sending messages.

To show the cursor you can use:

messageBus->Publish(new JamJar::Message(JamJar::Standard::WindowSystem::MESSAGE_REQUEST_SHOW_CURSOR));

To hide the cursor you can use:

messageBus->Publish(new JamJar::Message(JamJar::Standard::WindowSystem::MESSAGE_REQUEST_HIDE_CURSOR));

When these events are processed the appropriate message will be published to let other systems know if a cursor has been hidden or shown.

You can listen for these messages by listening out for:

  • JamJar::Standard::WindowSystem::MESSAGE_SHOW_CURSOR
  • JamJar::Standard::WindowSystem::MESSAGE_HIDE_CURSOR

These messages have no payload.

Fullscreen

The WindowSystem uses emscripten's fullscreen functions to handle fullscreen interactions (entering and exiting).

Entering Fullscreen

Fullscreen is set up using emscripten's defer functionality, meaning if you request enter fullscreen without user input it will defer it until the user does something (e.g. clicks the canvas), then it will enter fullscreen. This is because of web security features. See the emscripten documentation for more details.

You can enter fullscreen by sending a message:

#include "standard/window/window_system.hpp"
#include "message/message.hpp"

...

this->messageBus->Publish(new JamJar::Message(JamJar::Standard::WindowSystem::MESSAGE_REQUEST_ENTER_FULLSCREEN));

You can check if the request was successful by listening for these two events:

  • JamJar::Standard::WindowSystem::MESSAGE_ENTER_FULLSCREEN
  • JamJar::Standard::WindowSystem::MESSAGE_ENTER_FULLSCREEN_FAILURE

These messages are simple and do not contain any payload or additional data.

Exiting Fullscreen

You can exit fullscreen by sending a message:

#include "standard/window/window_system.hpp"
#include "message/message.hpp"

...

this->messageBus->Publish(new JamJar::Message(JamJar::Standard::WindowSystem::MESSAGE_REQUEST_EXIT_FULLSCREEN));

You can check if the request was successful by listening for these two events:

  • JamJar::Standard::WindowSystem::MESSAGE_EXIT_FULLSCREEN
  • JamJar::Standard::WindowSystem::MESSAGE_EXIT_FULLSCREEN_FAILURE

These messages are simple and do not contain any payload or additional data.