Support wayland fractional scale protocol

The new protocol adds support for more native communication of
fractional scaling.

Everything in the wayland backend already existed only our fractional
scale was calculated implicitly through a combination of output size
guesswork for fullscreen windows.

This new protocol makes that explicit, providing a more robust solution
and a solution for non-fullscreen surfaces. The fallback code is still
left in place for now whilst compositors gain support.
This commit is contained in:
David Edmundson
2022-07-11 19:28:37 +01:00
committed by Ethan Lee
parent 71d5f510c6
commit 6d2b74db66
5 changed files with 153 additions and 3 deletions

View File

@@ -52,6 +52,7 @@
#include "xdg-output-unstable-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "primary-selection-unstable-v1-client-protocol.h"
#include "fractional-scale-v1-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
@@ -884,7 +885,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
Wayland_init_xdg_output(d);
} else if (SDL_strcmp(interface, "wp_viewporter") == 0) {
d->viewporter = wl_registry_bind(d->registry, id, &wp_viewporter_interface, 1);
} else if (SDL_strcmp(interface, "wp_fractional_scale_manager_v1") == 0) {
d->fractional_scale_manager = wl_registry_bind(d->registry, id, &wp_fractional_scale_manager_v1_interface, 1);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id);
@@ -1136,6 +1138,11 @@ Wayland_VideoCleanup(_THIS)
data->primary_selection_device_manager = NULL;
}
if (data->fractional_scale_manager) {
wp_fractional_scale_manager_v1_destroy(data->fractional_scale_manager);
data->fractional_scale_manager = NULL;
}
if (data->compositor) {
wl_compositor_destroy(data->compositor);
data->compositor = NULL;

View File

@@ -75,6 +75,7 @@ typedef struct {
struct zwp_text_input_manager_v3 *text_input_manager;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wp_viewporter *viewporter;
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
EGLDisplay edpy;
EGLContext context;

View File

@@ -38,6 +38,7 @@
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "fractional-scale-v1-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
@@ -1104,7 +1105,10 @@ handle_surface_enter(void *data, struct wl_surface *surface,
/* Update the scale factor after the move so that fullscreen outputs are updated. */
Wayland_move_window(window->sdlwindow, driverdata);
update_scale_factor(window);
if (!window->fractional_scale) {
update_scale_factor(window);
}
}
static void
@@ -1142,7 +1146,9 @@ handle_surface_leave(void *data, struct wl_surface *surface,
window->outputs[window->num_outputs - 1]);
}
update_scale_factor(window);
if (!window->fractional_scale) {
update_scale_factor(window);
}
}
static const struct wl_surface_listener surface_listener = {
@@ -1581,6 +1587,29 @@ Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)
return 0;
}
void handle_preferred_scale_changed(void *data,
struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
uint preferred_scale)
{
SDL_WindowData *window = data;
float old_factor = window->scale_factor;
float new_factor = preferred_scale / 120.; /* 120 is a magic number defined in the spec as a common denominator*/
if (!(window->sdlwindow->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
/* Scale will always be 1, just ignore this */
return;
}
if (!FloatEqual(new_factor, old_factor)) {
Wayland_HandleResize(window->sdlwindow, window->sdlwindow->w, window->sdlwindow->h, new_factor);
}
}
static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
handle_preferred_scale_changed
};
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void SDLCALL
QtExtendedSurface_OnHintChanged(void *userdata, const char *name,
@@ -1999,6 +2028,12 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
Wayland_input_lock_pointer(c->input);
}
if (c->fractional_scale_manager) {
data->fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(c->fractional_scale_manager, data->surface);
wp_fractional_scale_v1_add_listener(data->fractional_scale,
&fractional_scale_listener, data);
}
/* Moved this call to ShowWindow: wl_surface_commit(data->surface); */
WAYLAND_wl_display_flush(c->display);
@@ -2192,6 +2227,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
wp_viewport_destroy(wind->draw_viewport);
}
if (wind->fractional_scale) {
wp_fractional_scale_v1_destroy(wind->fractional_scale);
}
SDL_free(wind->outputs);
if (wind->gles_swap_frame_callback) {

View File

@@ -83,6 +83,7 @@ typedef struct {
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
struct xdg_activation_token_v1 *activation_token;
struct wp_viewport *draw_viewport;
struct wp_fractional_scale_v1 *fractional_scale;
/* floating dimensions for restoring from maximized and fullscreen */
int floating_width, floating_height;