@@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2828
2929#if CFG_OS_NAME == CFG_OS_NAME_EMSCRIPTEN
3030# include < emscripten.h>
31+ # include < emscripten/html5.h>
3132#endif
3233
3334#if CFG_COMPILER == CFG_COMPILER_MSVC
@@ -374,6 +375,37 @@ class window_wrapper : public utki::destructable
374375
375376 SDL_Window* const window;
376377
378+ #if CFG_OS_NAME == CFG_OS_NAME_EMSCRIPTEN
379+ static bool on_emscripten_canvas_size_changed_callback (int event_type, const void * reserved, void * user_data)
380+ {
381+ if (!user_data) {
382+ std::cout << " emscripten_get_canvas_element_size(#canvas): user_data is nullptr" << std::endl;
383+ return false ;
384+ }
385+ auto * ww = reinterpret_cast <sdl_window_wrapper*>(user_data);
386+
387+ double width;
388+ double height;
389+
390+ if (auto res = emscripten_get_element_css_size (" #canvas" , &width, &height);
391+ res != EMSCRIPTEN_RESULT_SUCCESS)
392+ {
393+ std::cout << " emscripten_get_canvas_element_size(#canvas): failed, error = " << res << std::endl;
394+ return false ;
395+ }
396+
397+ // std::cout << "emscripten_get_canvas_element_size(#canvas): new canvas size = " << width << " " << height << std::endl;
398+
399+ SDL_SetWindowSize (
400+ ww->window , //
401+ int (width),
402+ int (height)
403+ );
404+
405+ return true ;
406+ }
407+ #endif
408+
377409 sdl_window_wrapper (const window_params& wp) :
378410 scale_factor (get_display_scaling_factor()),
379411 window ([&]() {
@@ -395,12 +427,46 @@ class window_wrapper : public utki::destructable
395427 SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, ver.minor );
396428 }
397429
398- auto dims = wp.dims .to <ruis::real>();
430+ #if CFG_OS_NAME == CFG_OS_NAME_EMSCRIPTEN
431+ // Change to soft fullscreen mode before creating the window to set correct OpenGL viewport initially.
432+ {
433+ EmscriptenFullscreenStrategy strategy{};
434+ strategy = {
435+ .scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH,
436+ .canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF,
437+ .filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_NEAREST,
438+ .canvasResizedCallback = &sdl_window_wrapper::on_emscripten_canvas_size_changed_callback,
439+ .canvasResizedCallbackUserData = this
440+ };
441+ emscripten_enter_soft_fullscreen (" #canvas" , &strategy);
442+ }
399443
400- #if CFG_OS_NAME != CFG_OS_NAME_EMSCRIPTEN
444+ auto dims = []() {
445+ double width;
446+ double height;
447+
448+ if (auto res = emscripten_get_element_css_size (" #canvas" , &width, &height);
449+ res != EMSCRIPTEN_RESULT_SUCCESS)
450+ {
451+ throw std::runtime_error (
452+ utki::cat (
453+ " emscripten_get_canvas_element_size(#canvas): failed, error = " , //
454+ res
455+ )
456+ );
457+ }
458+ return ruis::vec2 (
459+ ruis::real (width), //
460+ ruis::real (height)
461+ );
462+ }();
463+ #else
464+ auto dims = wp.dims .to <ruis::real>();
401465 dims *= this ->scale_factor ;
402466#endif
403467
468+ // std::cout << "dims = " << dims << std::endl;
469+
404470 SDL_Window* window = SDL_CreateWindow (
405471 wp.title .c_str (),
406472 SDL_WINDOWPOS_UNDEFINED,
@@ -412,6 +478,7 @@ class window_wrapper : public utki::destructable
412478 if (!window) {
413479 std::runtime_error (utki::cat (" Could not create SDL window, SDL_Error: " , SDL_GetError ()));
414480 }
481+
415482 return window;
416483 }())
417484 {}
@@ -591,10 +658,25 @@ application::application(std::string name, const window_params& wp) :
591658 )),
592659 directory (get_application_directories(this ->name))
593660{
661+ auto & ww = get_impl (*this );
662+
663+ // Get actual window size, as it can differ from requested one.
664+ int width;
665+ int height;
666+ SDL_GetWindowSize (ww.window .window , &width, &height);
667+
668+ auto dims = ruis::vec2 (ruis::real (width), ruis::real (height));
669+
670+ // std::cout << "actual window size = " << dims << std::endl;
671+
672+ #if CFG_OS_NAME == CFG_OS_NAME_EMSCRIPTEN
673+ dims *= ww.window .scale_factor ;
674+ #endif
675+
594676 this ->update_window_rect (
595677 ruis::rect (
596678 {0 , 0 }, //
597- ruis::vec2 ( ruis::real (wp. dims . x ()), ruis::real (wp. dims . y ())) * get_impl (* this ). window . scale_factor
679+ dims
598680 )
599681 );
600682}
@@ -711,6 +793,10 @@ void main_loop_iteration(void* user_data)
711793 // window dimensions and update the viewport later only once
712794 new_win_dims.x () = ruis::real (e.window .data1 );
713795 new_win_dims.y () = ruis::real (e.window .data2 );
796+ #if CFG_OS_NAME == CFG_OS_NAME_EMSCRIPTEN
797+ new_win_dims *= ww.window .scale_factor ;
798+ #endif
799+ // std::cout << "new window dims = " << new_win_dims << std::endl;
714800 break ;
715801 case SDL_WINDOWEVENT_ENTER:
716802 handle_mouse_hover (*app, true , 0 );
0 commit comments