Skip to content

Commit

Permalink
wayland: Handle cases where the compositor does not scale the monitor…
Browse files Browse the repository at this point in the history
… viewport in its compositing space

The xdg-output spec was updated to clarify its usage rules, and what was previously thought to be a bug is actually valid behavior. Gnome, when not using 'scale-monitor-framebuffer', does not scale the viewport of the display in the global compositor space, and thus the physical and logical sizes of the display will match. This value still needs to be divided by the integer scale value to get the logical output dimensions in screen units though.
  • Loading branch information
Kontrabant committed Mar 16, 2023
1 parent 5dd317b commit c270d15
Showing 1 changed file with 15 additions and 24 deletions.
39 changes: 15 additions & 24 deletions src/video/wayland/SDL_waylandvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,24 +302,6 @@ static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xd
{
SDL_DisplayData *driverdata = (SDL_DisplayData *)data;

if (driverdata->screen_width != 0 && driverdata->screen_height != 0) {
/* FIXME: GNOME has a bug where the logical size does not account for
* scale, resulting in bogus viewport sizes.
*
* Until this is fixed, validate that _some_ kind of scaling is being
* done (we can't match exactly because fractional scaling can't be
* detected otherwise), then override if necessary.
* -flibit
*/
const float scale = (float)driverdata->screen_width / (float)width;
if ((scale == 1.0f) && (driverdata->scale_factor != 1.0f)) {
SDL_LogWarn(
SDL_LOG_CATEGORY_VIDEO,
"xdg_output scale did not match, overriding with wl_output scale");
return;
}
}

driverdata->screen_width = width;
driverdata->screen_height = height;
driverdata->has_logical_size = SDL_TRUE;
Expand Down Expand Up @@ -582,13 +564,22 @@ static void display_handle_done(void *data,
native_mode.driverdata = driverdata->output;

if (driverdata->has_logical_size) { /* If xdg-output is present... */
if (video->viewporter) {
/* ...and viewports are supported, calculate the true scale of the output. */
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
if (native_mode.pixel_w != driverdata->screen_width || native_mode.pixel_h != driverdata->screen_height) {
/* ...and the compositor scales the logical viewport... */
if (video->viewporter) {
/* ...and viewports are supported, calculate the true scale of the output. */
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
} else {
/* ...otherwise, the 'native' pixel values are a multiple of the logical screen size. */
driverdata->pixel_width = driverdata->screen_width * (int)driverdata->scale_factor;
driverdata->pixel_height = driverdata->screen_height * (int)driverdata->scale_factor;
}
} else {
/* ...otherwise, the 'native' pixel values are a multiple of the logical screen size. */
driverdata->pixel_width = driverdata->screen_width * (int)driverdata->scale_factor;
driverdata->pixel_height = driverdata->screen_height * (int)driverdata->scale_factor;
/* ...and the output viewport is not scaled in the global compositing
* space, the output dimensions need to be divided by the scale factor.
*/
driverdata->screen_width /= (int)driverdata->scale_factor;
driverdata->screen_height /= (int)driverdata->scale_factor;
}
} else {
/* Calculate the screen coordinates from the pixel values, if xdg-output isn't present.
Expand Down

0 comments on commit c270d15

Please sign in to comment.