1+ /*
2+ * Copyright 2025 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 <stdio.h>
9+ #include <assert.h>
10+ #include <emscripten/emscripten.h>
11+ #include <GL/glut.h>
12+
13+ typedef struct {
14+ int width ;
15+ int height ;
16+ } rect_size_t ;
17+
18+ static rect_size_t browser_window_size = { 0 , 0 };
19+ static rect_size_t glut_init_size = { 0 , 0 };
20+ static rect_size_t glut_reshape_size = { 0 , 0 };
21+
22+ void print_size_test (const char * name , rect_size_t rect_size ) {
23+ static int test_count = 0 ;
24+ printf ("Test %d: %s = %d x %d\n" , ++ test_count , name , rect_size .width , rect_size .height );
25+ }
26+
27+ int equal_size (rect_size_t rect_1 , rect_size_t rect_2 ) {
28+ return (rect_1 .width == rect_2 .width && rect_1 .height == rect_2 .height );
29+ }
30+
31+ /**
32+ * Obtain various dimensions
33+ */
34+ EM_JS (void , get_browser_window_size , (int * width , int * height ), {
35+ setValue (width , window .innerWidth , 'i32' );
36+ setValue (height , window .innerHeight , 'i32' );
37+ });
38+
39+ EM_JS (void , get_canvas_client_size , (int * width , int * height ), {
40+ const canvas = Module .canvas ;
41+ setValue (width , canvas .clientWidth , 'i32' );
42+ setValue (height , canvas .clientHeight , 'i32' );
43+ });
44+
45+ EM_JS (void , get_canvas_size , (int * width , int * height ), {
46+ const canvas = Module .canvas ;
47+ setValue (width , canvas .width , 'i32' );
48+ setValue (height , canvas .height , 'i32' );
49+ });
50+
51+ /**
52+ * Update canvas style with given width and height, then invoke window resize event
53+ */
54+ EM_JS (void , test_resize_with_CSS , (const char * position , const char * width , const char * height ), {
55+ const canvas = Module .canvas ;
56+ canvas .style .position = UTF8ToString (position );
57+ canvas .style .width = UTF8ToString (width );
58+ canvas .style .height = UTF8ToString (height );
59+
60+ window .dispatchEvent (new UIEvent ('resize' ));
61+ });
62+
63+ /**
64+ * Verify canvas and reshape callback match target size, and also that
65+ * canvas width, height matches canvas clientWidth, clientHeight
66+ */
67+ void assert_sizes_equal (rect_size_t target_size ) {
68+ /* verify target size match */
69+ rect_size_t canvas_size ;
70+ get_canvas_size (& canvas_size .width , & canvas_size .height );
71+ assert (equal_size (canvas_size , target_size ));
72+ assert (equal_size (glut_reshape_size , target_size ));
73+
74+ /* verify canvas client size match */
75+ rect_size_t canvas_client_size ;
76+ get_canvas_client_size (& canvas_client_size .width , & canvas_client_size .height );
77+ assert (equal_size (canvas_size , canvas_client_size ));
78+ }
79+
80+ /**
81+ * Resizing tests
82+ */
83+ void run_tests () {
84+
85+ /* startup */
86+ print_size_test ("startup, no CSS: canvas == glutReshapeFunc == glutInitWindow size" , glut_init_size );
87+ assert_sizes_equal (glut_init_size );
88+
89+ /* glutReshapeWindow */
90+ rect_size_t new_reshape_size = { glut_init_size .width + 40 , glut_init_size .height + 20 };
91+ print_size_test ("glut reshape, no CSS: canvas == glutReshapeFunc == glutReshapeWindow size" , new_reshape_size );
92+ glutReshapeWindow (new_reshape_size .width , new_reshape_size .height );
93+ assert_sizes_equal (new_reshape_size );
94+
95+ /* 100% scale CSS */
96+ print_size_test ("100% window scale CSS: canvas == glutReshapeFunc == browser window size" , browser_window_size );
97+ test_resize_with_CSS ("fixed" , "100%" , "100%" ); /* fixed, so canvas is driven by window size */
98+ assert_sizes_equal (browser_window_size );
99+
100+ /* specific pixel size CSS */
101+ rect_size_t css_pixels_size = { glut_init_size .width - 20 , glut_init_size .height + 40 };
102+ print_size_test ("specific pixel size CSS: canvas == glutReshapeFunc == CSS specific size" , css_pixels_size );
103+ char css_width [16 ], css_height [16 ];
104+ snprintf (css_width , 16 , "%dpx" , css_pixels_size .width );
105+ snprintf (css_height , 16 , "%dpx" , css_pixels_size .height );
106+ test_resize_with_CSS ("static" , css_width , css_height ); /* static, canvas is driven by CSS size */
107+ assert_sizes_equal (css_pixels_size );
108+
109+ /* mix of CSS scale and pixel size */
110+ rect_size_t css_mixed_size = { browser_window_size .width * 0.6 , 100 };
111+ print_size_test ("60% width, 100px height CSS: canvas == glutReshapeFunc == CSS mixed size" , css_mixed_size );
112+ test_resize_with_CSS ("fixed" , "60%" , "100px" ); /* fixed, canvas width is driven by window size */
113+ assert_sizes_equal (css_mixed_size );
114+
115+ /* run tests once */
116+ glutIdleFunc (NULL );
117+ emscripten_force_exit (0 );
118+ }
119+
120+ /**
121+ * Reshape callback
122+ */
123+ void reshape (int w , int h ) {
124+ glut_reshape_size .width = w ;
125+ glut_reshape_size .height = h ;
126+ }
127+
128+ int main (int argc , char * argv []) {
129+ /* Make glut initial canvas size be 1/2 of browser window */
130+ get_browser_window_size (& browser_window_size .width , & browser_window_size .height );
131+ glut_init_size .width = browser_window_size .width / 2 ;
132+ glut_init_size .height = browser_window_size .height / 2 ;
133+
134+ glutInit (& argc , argv );
135+ glutInitWindowSize (glut_init_size .width , glut_init_size .height );
136+ glutInitDisplayMode (GLUT_RGB );
137+ glutCreateWindow ("test_glut_resize.c" );
138+
139+ /* Set up glut callback functions */
140+ glutIdleFunc (run_tests );
141+ glutReshapeFunc (reshape );
142+ glutDisplayFunc (NULL );
143+
144+ glutMainLoop ();
145+ return 0 ;
146+ }
0 commit comments