@@ -47,6 +47,9 @@ static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
47
47
static SDL_FullscreenResult Emscripten_SetWindowFullscreen (SDL_VideoDevice * _this , SDL_Window * window , SDL_VideoDisplay * display , SDL_FullscreenOp fullscreen );
48
48
static void Emscripten_PumpEvents (SDL_VideoDevice * _this );
49
49
static void Emscripten_SetWindowTitle (SDL_VideoDevice * _this , SDL_Window * window );
50
+ static bool Emscripten_SetWindowPosition (SDL_VideoDevice * _this , SDL_Window * window );
51
+ static void Emscripten_ShowWindow (SDL_VideoDevice * _this , SDL_Window * window );
52
+ static void Emscripten_HideWindow (SDL_VideoDevice * _this , SDL_Window * window );
50
53
51
54
static bool pumpevents_has_run = false;
52
55
static int pending_swap_interval = -1 ;
@@ -166,12 +169,12 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
166
169
167
170
device -> CreateSDLWindow = Emscripten_CreateWindow ;
168
171
device -> SetWindowTitle = Emscripten_SetWindowTitle ;
169
- /*device->SetWindowIcon = Emscripten_SetWindowIcon;
170
- device->SetWindowPosition = Emscripten_SetWindowPosition;*/
172
+ /*device->SetWindowIcon = Emscripten_SetWindowIcon;*/
173
+ device -> SetWindowPosition = Emscripten_SetWindowPosition ;
171
174
device -> SetWindowSize = Emscripten_SetWindowSize ;
172
- /* device->ShowWindow = Emscripten_ShowWindow;
175
+ device -> ShowWindow = Emscripten_ShowWindow ;
173
176
device -> HideWindow = Emscripten_HideWindow ;
174
- device->RaiseWindow = Emscripten_RaiseWindow;
177
+ /* device->RaiseWindow = Emscripten_RaiseWindow;
175
178
device->MaximizeWindow = Emscripten_MaximizeWindow;
176
179
device->MinimizeWindow = Emscripten_MinimizeWindow;
177
180
device->RestoreWindow = Emscripten_RestoreWindow;
@@ -480,8 +483,7 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
480
483
selector = SDL_GetStringProperty (props , SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID , "#canvas" );
481
484
}
482
485
483
- // Since SDL3 doesn't create the canvas element in the DOM, it should be verified
484
- // that the canvas ID refers to an HTML5CanvasElement.
486
+ // If an element with this id already exists, it should be verified that it is to an HTML5CanvasElement
485
487
canvas_exists = MAIN_THREAD_EM_ASM_INT ({
486
488
var id = UTF8ToString ($0 );
487
489
try
@@ -498,8 +500,75 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
498
500
return false;
499
501
}, selector );
500
502
503
+ // Create the canvas if it doesn't exist. Assign a class to the element to signal that it was created by SDL3
501
504
if (!canvas_exists ) {
502
- SDL_SetError ("Element '%s' is either not a HTMLCanvasElement or doesn't exist" , selector );
505
+ int x = SDL_GetNumberProperty (props , SDL_PROP_WINDOW_CREATE_X_NUMBER , SDL_WINDOWPOS_UNDEFINED );
506
+ if (SDL_WINDOWPOS_ISUNDEFINED (x )) {
507
+ x = 0 ;
508
+ }
509
+ int y = SDL_GetNumberProperty (props , SDL_PROP_WINDOW_CREATE_Y_NUMBER , SDL_WINDOWPOS_UNDEFINED );
510
+ if (SDL_WINDOWPOS_ISUNDEFINED (y )) {
511
+ y = 0 ;
512
+ }
513
+ const int w = SDL_GetNumberProperty (props , SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER , 0 );
514
+ const int h = SDL_GetNumberProperty (props , SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER , 0 );
515
+ SDL_Window * parent = SDL_GetPointerProperty (props , SDL_PROP_WINDOW_CREATE_PARENT_POINTER , NULL );
516
+ const char * parent_id ;
517
+ if (parent ) {
518
+ SDL_WindowData * parent_window_data = parent -> internal ;
519
+ parent_id = parent_window_data -> canvas_id ;
520
+ } else {
521
+ parent_id = "body" ;
522
+ }
523
+ canvas_exists = MAIN_THREAD_EM_ASM_INT ({
524
+ try
525
+ {
526
+ var id = UTF8ToString ($0 );
527
+ var x = $1 ;
528
+ var y = $2 ;
529
+ var w = $3 ;
530
+ var h = $4 ;
531
+ var parent_id = UTF8ToString ($5 );
532
+ var x_centered = $6 ;
533
+ var y_centered = $7 ;
534
+ if (x_centered ) {
535
+ x = window .innerWidth / 2 - w / 2 ;
536
+ }
537
+ if (y_centered ) {
538
+ y = window .innerHeight / 2 - h / 2 ;
539
+ }
540
+ var canvas = document .querySelector (id );
541
+ if (canvas ) {
542
+ // Element with this id is not a canvas
543
+ return false;
544
+ }
545
+ canvas = document .createElement ("canvas" );
546
+ canvas .classList .add ("SDL3_canvas" );
547
+ canvas .id = id .replace ("#" , "" );
548
+ canvas .oncontextmenu = (e ) = > { e .preventDefault (); };
549
+ canvas .style .position = "absolute" ;
550
+ canvas .style .left = `$ {x }px `;
551
+ canvas .style .top = `$ {y }px `;
552
+ canvas .width = w ;
553
+ canvas .height = h ;
554
+ var parent = document .querySelector (parent_id );
555
+ if (parent_id != = "body" && parent ) {
556
+ parent .parentNode .append (canvas );
557
+ } else {
558
+ document .body .append (canvas );
559
+ }
560
+ return true;
561
+ }
562
+ catch (e )
563
+ {
564
+ // querySelector throws if id isn't a valid selector
565
+ }
566
+ return false;
567
+ }, selector , x , y , w , h , parent_id , SDL_WINDOWPOS_CENTERED_DISPLAY (x ), SDL_WINDOWPOS_CENTERED_DISPLAY (y ));
568
+ }
569
+
570
+ if (!canvas_exists ) {
571
+ SDL_SetError ("'%s' is not a valid selector or doesn't refer to an HTMLCanvasElement" , selector );
503
572
return false;
504
573
}
505
574
@@ -617,8 +686,20 @@ static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
617
686
618
687
Emscripten_UnregisterEventHandlers (data );
619
688
620
- // We can't destroy the canvas, so resize it to zero instead
621
- emscripten_set_canvas_element_size (data -> canvas_id , 0 , 0 );
689
+ MAIN_THREAD_EM_ASM ({
690
+ var id = UTF8ToString ($0 );
691
+ var canvas = document .querySelector (id );
692
+ if (canvas ) {
693
+ if (canvas .classList .contains ("SDL3_canvas" )) {
694
+ canvas .remove ();
695
+ } else {
696
+ // Since the canvas wasn't created by SDL3, just resize it to zero instead.
697
+ // TODO: Is this necessary?
698
+ canvas .width = 0 ;
699
+ canvas .height = 0 ;
700
+ }
701
+ }
702
+ }, data -> canvas_id );
622
703
623
704
vdata = _this -> internal ;
624
705
SDL_SetBooleanProperty (vdata -> window_map , data -> canvas_id , false);
@@ -685,4 +766,57 @@ static void Emscripten_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window
685
766
emscripten_set_window_title (window -> title );
686
767
}
687
768
769
+ static bool Emscripten_SetWindowPosition (SDL_VideoDevice * _this , SDL_Window * window )
770
+ {
771
+ SDL_WindowData * window_data = window -> internal ;
772
+ return MAIN_THREAD_EM_ASM_INT ({
773
+ try
774
+ {
775
+ var id = UTF8ToString ($0 );
776
+ var x = $1 ;
777
+ var y = $2 ;
778
+ var canvas = document .querySelector (id );
779
+ if (canvas && canvas .style .position && canvas .style .position != = 'static' ) {
780
+ canvas .style .left = `$ {x }px `;
781
+ canvas .style .top = `$ {y }px `;
782
+ return true;
783
+ }
784
+ }
785
+ catch (e )
786
+ {
787
+ // querySelector throws if id is not a valid selector
788
+ }
789
+ return false;
790
+ }, window_data -> canvas_id , window -> pending .x , window -> pending .y );
791
+ }
792
+
793
+ static void Emscripten_SetWindowDisplay (SDL_Window * window , const char * display )
794
+ {
795
+ SDL_WindowData * window_data = window -> internal ;
796
+ MAIN_THREAD_EM_ASM ({
797
+ var id = UTF8ToString ($0 );
798
+ var display = UTF8ToString ($1 );
799
+ try
800
+ {
801
+ let canvas = document .querySelector (id );
802
+ if (canvas ) {
803
+ canvas .style .display = display ;
804
+ }
805
+ }
806
+ catch (e )
807
+ {
808
+ // querySelector throws if id is not a valid selector
809
+ }
810
+ }, window_data -> canvas_id , display );
811
+ }
812
+
813
+ static void Emscripten_ShowWindow (SDL_VideoDevice * _this , SDL_Window * window )
814
+ {
815
+ Emscripten_SetWindowDisplay (window , "" );
816
+ }
817
+
818
+ static void Emscripten_HideWindow (SDL_VideoDevice * _this , SDL_Window * window )
819
+ {
820
+ Emscripten_SetWindowDisplay (window , "none" );
821
+ }
688
822
#endif // SDL_VIDEO_DRIVER_EMSCRIPTEN
0 commit comments