@@ -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
@@ -2334,6 +2337,13 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
23342337 output = NULL ;
23352338 }
23362339 }
2340+
2341+ // Commit to preserve any pending client viewport dimensions before entering fullscreen.
2342+ if (fullscreen == SDL_FULLSCREEN_OP_ENTER && !(window -> flags & SDL_WINDOW_MAXIMIZED ) &&
2343+ wind -> pending_client_viewport_dimensions ) {
2344+ wind -> pending_client_viewport_dimensions = false;
2345+ wl_surface_commit (wind -> surface );
2346+ }
23372347 SetFullscreen (window , output , !!fullscreen );
23382348 } else if (wind -> is_fullscreen ) {
23392349 /*
@@ -2462,8 +2472,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
24622472 return ; // Can't do anything yet, wait for ShowWindow
24632473 }
24642474
2465- // Commit to preserve any pending size data.
2466- wl_surface_commit (wind -> surface );
2475+ // Commit to preserve any pending viewport size data.
2476+ if (wind -> pending_client_viewport_dimensions ) {
2477+ wind -> pending_client_viewport_dimensions = false;
2478+ wl_surface_commit (wind -> surface );
2479+ }
24672480 libdecor_frame_set_maximized (wind -> shell_surface .libdecor .frame );
24682481
24692482 ++ wind -> window_state_deadline_count ;
@@ -2476,8 +2489,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
24762489 return ; // Can't do anything yet, wait for ShowWindow
24772490 }
24782491
2479- // Commit to preserve any pending size data.
2480- wl_surface_commit (wind -> surface );
2492+ // Commit to preserve any pending viewport size data.
2493+ if (wind -> pending_client_viewport_dimensions ) {
2494+ wind -> pending_client_viewport_dimensions = false;
2495+ wl_surface_commit (wind -> surface );
2496+ }
24812497 xdg_toplevel_set_maximized (wind -> shell_surface .xdg .toplevel .xdg_toplevel );
24822498
24832499 ++ wind -> window_state_deadline_count ;
@@ -2719,12 +2735,10 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
27192735 wl_callback_add_listener (data -> gles_swap_frame_callback , & gles_swap_frame_listener , data );
27202736 }
27212737
2722- // No frame callback on external surfaces as it may already have one attached.
2723- if (!external_surface ) {
2724- // Fire a callback when the compositor wants a new frame to set the surface damage region.
2725- data -> surface_frame_callback = wl_surface_frame (data -> surface );
2726- wl_callback_add_listener (data -> surface_frame_callback , & surface_frame_listener , data );
2727- }
2738+ // Fire a callback when the compositor wants a new frame.
2739+ data -> surface_wrapper = WAYLAND_wl_proxy_create_wrapper (data -> surface );
2740+ data -> surface_frame_callback = wl_surface_frame (data -> surface_wrapper );
2741+ wl_callback_add_listener (data -> surface_frame_callback , & surface_frame_listener , data );
27282742
27292743 if (window -> flags & SDL_WINDOW_TRANSPARENT ) {
27302744 if (_this -> gl_config .alpha_size == 0 ) {
@@ -2856,6 +2870,11 @@ void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
28562870 wind -> requested .pixel_height = window -> pending .h ;
28572871 }
28582872
2873+ if (wind -> requested .logical_width != wind -> current .logical_width ||
2874+ wind -> requested .logical_height != wind -> current .logical_height ) {
2875+ wind -> pending_client_viewport_dimensions = true;
2876+ }
2877+
28592878 ConfigureWindowGeometry (window );
28602879 } else {
28612880 // Can't resize the window.
0 commit comments