@@ -656,43 +656,46 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
656656{
657657 SDL_WindowData * wind = (SDL_WindowData * )data ;
658658
659- /* XXX: This is needed to work around an Nvidia egl-wayland bug due to buffer coordinates
660- * being used with wl_surface_damage, which causes part of the output to not be
661- * updated when using a viewport with an output region larger than the source region.
662- */
663- if (wl_compositor_get_version (wind -> waylandData -> compositor ) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION ) {
664- wl_surface_damage_buffer (wind -> surface , 0 , 0 , SDL_MAX_SINT32 , SDL_MAX_SINT32 );
665- } else {
666- wl_surface_damage (wind -> surface , 0 , 0 , SDL_MAX_SINT32 , SDL_MAX_SINT32 );
667- }
668-
669659 wind -> drop_interactive_resizes = false;
660+ wind -> pending_client_viewport_dimensions = false;
670661
671- if (wind -> shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME ) {
672- wind -> shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_SHOWN ;
673-
674- // If any child windows are waiting on this window to be shown, show them now
675- for (SDL_Window * w = wind -> sdlwindow -> first_child ; w ; w = w -> next_sibling ) {
676- if (w -> internal -> shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOW_PENDING ) {
677- Wayland_ShowWindow (SDL_GetVideoDevice (), w );
678- } else if (w -> internal -> reparenting_required ) {
679- Wayland_SetWindowParent (SDL_GetVideoDevice (), w , w -> parent );
680- if (w -> flags & SDL_WINDOW_MODAL ) {
681- Wayland_SetWindowModal (SDL_GetVideoDevice (), w , true);
662+ if (!(wind -> sdlwindow -> flags & SDL_WINDOW_EXTERNAL )) {
663+ /* XXX: This is needed to work around an Nvidia egl-wayland bug due to buffer coordinates
664+ * being used with wl_surface_damage, which causes part of the output to not be
665+ * updated when using a viewport with an output region larger than the source region.
666+ */
667+ if (wl_compositor_get_version (wind -> waylandData -> compositor ) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION ) {
668+ wl_surface_damage_buffer (wind -> surface , 0 , 0 , SDL_MAX_SINT32 , SDL_MAX_SINT32 );
669+ } else {
670+ wl_surface_damage (wind -> surface , 0 , 0 , SDL_MAX_SINT32 , SDL_MAX_SINT32 );
671+ }
672+
673+ if (wind -> shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME ) {
674+ wind -> shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_SHOWN ;
675+
676+ // If any child windows are waiting on this window to be shown, show them now
677+ for (SDL_Window * w = wind -> sdlwindow -> first_child ; w ; w = w -> next_sibling ) {
678+ if (w -> internal -> shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOW_PENDING ) {
679+ Wayland_ShowWindow (SDL_GetVideoDevice (), w );
680+ } else if (w -> internal -> reparenting_required ) {
681+ Wayland_SetWindowParent (SDL_GetVideoDevice (), w , w -> parent );
682+ if (w -> flags & SDL_WINDOW_MODAL ) {
683+ Wayland_SetWindowModal (SDL_GetVideoDevice (), w , true);
684+ }
682685 }
683686 }
684- }
685687
686- /* If the window was initially set to the suspended state, send the occluded event now,
687- * as we don't want to mark the window as occluded until at least one frame has been submitted.
688- */
689- if (wind -> suspended ) {
690- SDL_SendWindowEvent (wind -> sdlwindow , SDL_EVENT_WINDOW_OCCLUDED , 0 , 0 );
688+ /* If the window was initially set to the suspended state, send the occluded event now,
689+ * as we don't want to mark the window as occluded until at least one frame has been submitted.
690+ */
691+ if (wind -> suspended ) {
692+ SDL_SendWindowEvent (wind -> sdlwindow , SDL_EVENT_WINDOW_OCCLUDED , 0 , 0 );
693+ }
691694 }
692695 }
693696
694697 wl_callback_destroy (cb );
695- wind -> surface_frame_callback = wl_surface_frame (wind -> surface );
698+ wind -> surface_frame_callback = wl_surface_frame (wind -> surface_wrapper );
696699 wl_callback_add_listener (wind -> surface_frame_callback , & surface_frame_listener , data );
697700}
698701
@@ -2331,6 +2334,13 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
23312334 output = NULL ;
23322335 }
23332336 }
2337+
2338+ // Commit to preserve any pending client viewport dimensions before entering fullscreen.
2339+ if (fullscreen == SDL_FULLSCREEN_OP_ENTER && !(window -> flags & SDL_WINDOW_MAXIMIZED ) &&
2340+ wind -> pending_client_viewport_dimensions ) {
2341+ wind -> pending_client_viewport_dimensions = false;
2342+ wl_surface_commit (wind -> surface );
2343+ }
23342344 SetFullscreen (window , output , !!fullscreen );
23352345 } else if (wind -> is_fullscreen ) {
23362346 /*
@@ -2459,8 +2469,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
24592469 return ; // Can't do anything yet, wait for ShowWindow
24602470 }
24612471
2462- // Commit to preserve any pending size data.
2463- wl_surface_commit (wind -> surface );
2472+ // Commit to preserve any pending viewport size data.
2473+ if (wind -> pending_client_viewport_dimensions ) {
2474+ wind -> pending_client_viewport_dimensions = false;
2475+ wl_surface_commit (wind -> surface );
2476+ }
24642477 libdecor_frame_set_maximized (wind -> shell_surface .libdecor .frame );
24652478
24662479 ++ wind -> window_state_deadline_count ;
@@ -2473,8 +2486,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
24732486 return ; // Can't do anything yet, wait for ShowWindow
24742487 }
24752488
2476- // Commit to preserve any pending size data.
2477- wl_surface_commit (wind -> surface );
2489+ // Commit to preserve any pending viewport size data.
2490+ if (wind -> pending_client_viewport_dimensions ) {
2491+ wind -> pending_client_viewport_dimensions = false;
2492+ wl_surface_commit (wind -> surface );
2493+ }
24782494 xdg_toplevel_set_maximized (wind -> shell_surface .xdg .toplevel .xdg_toplevel );
24792495
24802496 ++ wind -> window_state_deadline_count ;
@@ -2716,12 +2732,10 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
27162732 wl_callback_add_listener (data -> gles_swap_frame_callback , & gles_swap_frame_listener , data );
27172733 }
27182734
2719- // No frame callback on external surfaces as it may already have one attached.
2720- if (!external_surface ) {
2721- // Fire a callback when the compositor wants a new frame to set the surface damage region.
2722- data -> surface_frame_callback = wl_surface_frame (data -> surface );
2723- wl_callback_add_listener (data -> surface_frame_callback , & surface_frame_listener , data );
2724- }
2735+ // Fire a callback when the compositor wants a new frame.
2736+ data -> surface_wrapper = WAYLAND_wl_proxy_create_wrapper (data -> surface );
2737+ data -> surface_frame_callback = wl_surface_frame (data -> surface_wrapper );
2738+ wl_callback_add_listener (data -> surface_frame_callback , & surface_frame_listener , data );
27252739
27262740 if (window -> flags & SDL_WINDOW_TRANSPARENT ) {
27272741 if (_this -> gl_config .alpha_size == 0 ) {
@@ -2853,6 +2867,11 @@ void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
28532867 wind -> requested .pixel_height = window -> pending .h ;
28542868 }
28552869
2870+ if (wind -> requested .logical_width != wind -> current .logical_width ||
2871+ wind -> requested .logical_height != wind -> current .logical_height ) {
2872+ wind -> pending_client_viewport_dimensions = true;
2873+ }
2874+
28562875 ConfigureWindowGeometry (window );
28572876 } else {
28582877 // Can't resize the window.
0 commit comments