Skip to content

Commit b7210dc

Browse files
committed
added test for the CSS scaling feature
1 parent 0b2717d commit b7210dc

File tree

3 files changed

+125
-16
lines changed

3 files changed

+125
-16
lines changed

src/library_glfw.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,14 +1113,7 @@ var LibraryGLFW = {
11131113
// Get non alive id
11141114
const canvas = Module['canvas'];
11151115

1116-
var clientWidth = canvas.clientWidth;
1117-
var clientHeight = canvas.clientHeight;
1118-
if (GLFW.isCSSScalingEnabled()) {
1119-
clientWidth = width;
1120-
clientHeight = height;
1121-
}
1122-
1123-
var win = new GLFW_Window(id, clientWidth, clientHeight, canvas.width, canvas.height, title, monitor, share);
1116+
var win = new GLFW_Window(id, width, height, canvas.width, canvas.height, title, monitor, share);
11241117

11251118
// Set window to array
11261119
if (id - 1 == GLFW.windows.length) {
@@ -1331,14 +1324,7 @@ var LibraryGLFW = {
13311324

13321325
adjustCanvasDimensions() {
13331326
if (GLFW.active) {
1334-
const canvas = Module['canvas'];
1335-
var clientWidth = canvas.clientWidth;
1336-
var clientHeight = canvas.clientHeight;
1337-
if (GLFW.isCSSScalingEnabled()) {
1338-
clientWidth = GLFW.active.width;
1339-
clientHeight = GLFW.active.height;
1340-
}
1341-
Browser.updateCanvasDimensions(canvas, clientWidth, clientHeight);
1327+
Browser.updateCanvasDimensions(Module['canvas'], GLFW.active.width, GLFW.active.height);
13421328
Browser.updateResizeListeners();
13431329
}
13441330
},
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2024 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <GLFW/glfw3.h>
9+
#include <assert.h>
10+
#include <emscripten/html5.h>
11+
#include <stdio.h>
12+
13+
/*
14+
* History:
15+
* - This test was added after the issue #22847 was reported (November 2024).
16+
* - For historical reasons, the JavaScript GLFW implementation includes a feature: the ability to scale the canvas via CSS.
17+
* - Note that this feature is not part of GLFW as GLFW does not offer any API to scale the window.
18+
* - Being undocumented/untested, this feature was accidentally removed when HiDPI support was added (in 3.1.51 / December 2023).
19+
* - This test was added to document this feature and ensure proper behavior.
20+
*
21+
* What does this feature do?
22+
* - if there is a CSS rule that specifies the size of the canvas (ex: `#canvas { width: 100%;}`), then the canvas
23+
* will be scaled to match this value. Note that from a GLFW point of view, the size of the window remains what
24+
* gets specified in `glfwCreateWindow` and/or `glfwSetWindowSize`
25+
* - only global CSS rules apply, as setting a CSS rule on the canvas itself is removed (ex: `<canvas style="width:100%;">` is ignored)
26+
*
27+
* In HiDPI mode, (`glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE)`), this feature cannot work and as a result is disabled (because the canvas
28+
* is sized using `devicePixelRatio` as the factor and CSS is used to scale it at the desired size).
29+
*/
30+
31+
/**
32+
* As explained above, this function adds a global CSS rule instead of setting the CSS style directly on the canvas
33+
* because it gets ignored otherwise. */
34+
EM_JS(void, addCSSScalingRule, (), {
35+
const style = document.createElement('style');
36+
style.appendChild(document.createTextNode("#canvas { width: 700px; height: 500px; }"));
37+
document.head.appendChild(style);
38+
})
39+
40+
/**
41+
* Since it is unclear in which browser/resolution this test will run we compute the actual ratio used by the test.
42+
* This has the neat effect that the test can be run manually on a HiDPI screen.
43+
*/
44+
EM_JS(double, getDevicePixelRatio, (), {return (typeof devicePixelRatio == 'number' && devicePixelRatio) || 1.0;})
45+
46+
/**
47+
* Checks window size and framebuffer size according to ratio */
48+
static void checkWindowSize(GLFWwindow *window, int expectedWidth, int expectedHeight, float ratio) {
49+
// first check the window size
50+
int w, h;
51+
glfwGetWindowSize(window, &w, &h);
52+
printf("windowSize => %d == %d && %d == %d\n", w, expectedWidth, h, expectedHeight);
53+
assert(w == expectedWidth && h == expectedHeight);
54+
55+
// second check the frame buffer size
56+
int fbw, fbh;
57+
glfwGetFramebufferSize(window, &fbw, &fbh);
58+
printf("framebufferSize => %d == %d && %d == %d\n", fbw, (int) (expectedWidth * ratio), fbh, (int) (expectedHeight * ratio));
59+
assert(fbw == (int) (expectedWidth * ratio) && fbh == (int) (expectedHeight * ratio));
60+
}
61+
62+
int main() {
63+
64+
assert(glfwInit() == GLFW_TRUE);
65+
66+
// Use Case #1
67+
// Create a window without HiDPI support and without CSS rule => expected sizes to match
68+
{
69+
printf("Use case #1\n");
70+
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
71+
assert(window);
72+
checkWindowSize(window, 640, 480, 1.0);
73+
double w, h;
74+
emscripten_get_element_css_size("#canvas", &w, &h);
75+
printf("CSS Size=%.0fx%.0f\n", w, h);
76+
assert(w == 640 && h == 480);
77+
glfwDestroyWindow(window);
78+
}
79+
80+
// Use Case #2
81+
// Create a window without HiDPI support, and with CSS rule =>
82+
// the window size should match the creation size, but the CSS size should match the rule.
83+
{
84+
printf("Use case #2\n");
85+
addCSSScalingRule();
86+
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
87+
assert(window);
88+
checkWindowSize(window, 640, 480, 1.0);
89+
double w, h;
90+
emscripten_get_element_css_size("#canvas", &w, &h);
91+
printf("CSS Size=%.0fx%.0f\n", w, h);
92+
assert(w == 700 && h == 500); // Rule is "#canvas { width: 700px; height: 500px; }"
93+
glfwDestroyWindow(window);
94+
}
95+
96+
// Use Case #3
97+
// Create a window with HiDPI support, and with CSS rule =>
98+
// the window size and framebuffer size should match the creation size (CSS rule is ignored)
99+
{
100+
printf("Use case #3\n");
101+
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
102+
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
103+
assert(window);
104+
double dpr = getDevicePixelRatio();
105+
printf("devicePixelRatio=%.0f\n", dpr);
106+
checkWindowSize(window, 640, 480, dpr);
107+
double w, h;
108+
emscripten_get_element_css_size("#canvas", &w, &h);
109+
printf("CSS Size=%.0fx%.0f\n", w, h);
110+
assert(w == 640 && h == 480);
111+
glfwDestroyWindow(window);
112+
}
113+
114+
printf("All tests complete\n");
115+
116+
glfwTerminate();
117+
118+
return 0;
119+
}

test/test_browser.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,10 @@ def test_glfw_events(self, args):
28642864
def test_glfw3_hi_dpi_aware(self):
28652865
self.btest_exit('test_glfw3_hi_dpi_aware.c', args=['-sUSE_GLFW=3', '-lGL'])
28662866

2867+
@requires_graphics_hardware
2868+
def test_glfw3_css_scaling(self):
2869+
self.btest_exit('test_glfw3_css_scaling.c', args=['-sUSE_GLFW=3'])
2870+
28672871
@requires_graphics_hardware
28682872
@also_with_wasm2js
28692873
def test_sdl2_image(self):

0 commit comments

Comments
 (0)