@@ -656,43 +656,46 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
656
656
{
657
657
SDL_WindowData * wind = (SDL_WindowData * )data ;
658
658
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
-
669
659
wind -> drop_interactive_resizes = false;
660
+ wind -> pending_client_viewport_dimensions = false;
661
+
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 ;
670
675
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);
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
+ }
682
685
}
683
686
}
684
- }
685
687
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
+ }
691
694
}
692
695
}
693
696
694
697
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 );
696
699
wl_callback_add_listener (wind -> surface_frame_callback , & surface_frame_listener , data );
697
700
}
698
701
@@ -2334,6 +2337,13 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
2334
2337
output = NULL ;
2335
2338
}
2336
2339
}
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
+ }
2337
2347
SetFullscreen (window , output , !!fullscreen );
2338
2348
} else if (wind -> is_fullscreen ) {
2339
2349
/*
@@ -2462,8 +2472,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
2462
2472
return ; // Can't do anything yet, wait for ShowWindow
2463
2473
}
2464
2474
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
+ }
2467
2480
libdecor_frame_set_maximized (wind -> shell_surface .libdecor .frame );
2468
2481
2469
2482
++ wind -> window_state_deadline_count ;
@@ -2476,8 +2489,11 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
2476
2489
return ; // Can't do anything yet, wait for ShowWindow
2477
2490
}
2478
2491
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
+ }
2481
2497
xdg_toplevel_set_maximized (wind -> shell_surface .xdg .toplevel .xdg_toplevel );
2482
2498
2483
2499
++ wind -> window_state_deadline_count ;
@@ -2719,12 +2735,10 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
2719
2735
wl_callback_add_listener (data -> gles_swap_frame_callback , & gles_swap_frame_listener , data );
2720
2736
}
2721
2737
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 );
2728
2742
2729
2743
if (window -> flags & SDL_WINDOW_TRANSPARENT ) {
2730
2744
if (_this -> gl_config .alpha_size == 0 ) {
@@ -2856,6 +2870,11 @@ void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
2856
2870
wind -> requested .pixel_height = window -> pending .h ;
2857
2871
}
2858
2872
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
+
2859
2878
ConfigureWindowGeometry (window );
2860
2879
} else {
2861
2880
// Can't resize the window.
@@ -3203,6 +3222,10 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
3203
3222
wl_callback_destroy (wind -> surface_frame_callback );
3204
3223
}
3205
3224
3225
+ if (wind -> surface_wrapper ) {
3226
+ WAYLAND_wl_proxy_wrapper_destroy (wind -> surface_wrapper );
3227
+ }
3228
+
3206
3229
if (!(window -> flags & SDL_WINDOW_EXTERNAL )) {
3207
3230
wl_surface_destroy (wind -> surface );
3208
3231
} else {
0 commit comments