mirror of https://github.com/snes9xgit/snes9x.git
Gtk/Wayland: Support fractional scale.
This commit is contained in:
parent
9972e2df56
commit
f1286eda4c
|
@ -140,7 +140,9 @@ if(USE_WAYLAND)
|
|||
src/gtk_wayland_egl_context.h
|
||||
src/gtk_wayland_surface.cpp
|
||||
src/gtk_wayland_surface.h
|
||||
src/wayland-idle-inhibit-unstable-v1.c)
|
||||
src/wayland-idle-inhibit-unstable-v1.c
|
||||
src/viewporter-client-protocol.c
|
||||
src/fractional-scale-v1.c)
|
||||
list(APPEND ARGS ${WAYLAND_CFLAGS})
|
||||
list(APPEND LIBS ${WAYLAND_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
@ -31,26 +31,29 @@ void S9xVulkanDisplayDriver::refresh()
|
|||
if (!context)
|
||||
return;
|
||||
|
||||
bool vsync_changed = context->swapchain->set_vsync(gui_config->sync_to_vblank);
|
||||
context->swapchain->set_vsync(gui_config->sync_to_vblank);
|
||||
int new_width, new_height;
|
||||
|
||||
auto new_width = drawing_area->get_width() * drawing_area->get_scale_factor();
|
||||
auto new_height = drawing_area->get_height() * drawing_area->get_scale_factor();
|
||||
|
||||
if (new_width != current_width || new_height != current_height || vsync_changed)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
{
|
||||
wayland_surface->resize();
|
||||
}
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
{
|
||||
wayland_surface->resize();
|
||||
std::tie(new_width, new_height) = wayland_surface->get_size();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
new_width = drawing_area->get_width() * drawing_area->get_scale_factor();
|
||||
new_height = drawing_area->get_height() * drawing_area->get_scale_factor();
|
||||
}
|
||||
|
||||
if (new_width != current_width || new_height != current_height)
|
||||
{
|
||||
context->recreate_swapchain(new_width, new_height);
|
||||
context->wait_idle();
|
||||
current_width = new_width;
|
||||
current_height = new_height;
|
||||
}
|
||||
|
||||
context->swapchain->set_vsync(gui_config->sync_to_vblank);
|
||||
}
|
||||
|
||||
int S9xVulkanDisplayDriver::init()
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
#include "fractional-scale-v1.h"
|
||||
#include "gtk_s9x.h"
|
||||
#include "gtk_wayland_surface.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
static void wl_global(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
|
@ -25,6 +28,10 @@ static void wl_global(void *data,
|
|||
wl->subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
|
||||
else if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name))
|
||||
wl->idle_inhibit_manager = (struct zwp_idle_inhibit_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_idle_inhibit_manager_v1_interface, 1);
|
||||
else if (!strcmp(interface, wp_viewporter_interface.name))
|
||||
wl->viewporter = (struct wp_viewporter *)wl_registry_bind(wl_registry, name, &wp_viewporter_interface, 1);
|
||||
else if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name))
|
||||
wl->fractional_scale_manager = (struct wp_fractional_scale_manager_v1 *)wl_registry_bind(wl_registry, name, &wp_fractional_scale_manager_v1_interface, 1);
|
||||
}
|
||||
|
||||
static void wl_global_remove(void *data,
|
||||
|
@ -50,6 +57,11 @@ WaylandSurface::WaylandSurface()
|
|||
subsurface = nullptr;
|
||||
idle_inhibit_manager = nullptr;
|
||||
idle_inhibitor = nullptr;
|
||||
viewporter = nullptr;
|
||||
viewport = nullptr;
|
||||
fractional_scale_manager = nullptr;
|
||||
fractional_scale = nullptr;
|
||||
actual_scale = 0.0;
|
||||
}
|
||||
|
||||
WaylandSurface::~WaylandSurface()
|
||||
|
@ -68,8 +80,32 @@ WaylandSurface::~WaylandSurface()
|
|||
|
||||
if (child)
|
||||
wl_surface_destroy(child);
|
||||
|
||||
if (viewporter)
|
||||
wp_viewporter_destroy(viewporter);
|
||||
|
||||
if (viewport)
|
||||
wp_viewport_destroy(viewport);
|
||||
|
||||
if (fractional_scale_manager)
|
||||
wp_fractional_scale_manager_v1_destroy(fractional_scale_manager);
|
||||
|
||||
if (fractional_scale)
|
||||
wp_fractional_scale_v1_destroy(fractional_scale);
|
||||
}
|
||||
|
||||
static void preferred_scale(void *data,
|
||||
struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
|
||||
uint32_t scale)
|
||||
{
|
||||
((WaylandSurface *)data)->actual_scale = scale / 120.0;
|
||||
}
|
||||
|
||||
wp_fractional_scale_v1_listener fractional_scale_v1_listener =
|
||||
{
|
||||
preferred_scale
|
||||
};
|
||||
|
||||
bool WaylandSurface::attach(GtkWidget *widget)
|
||||
{
|
||||
GdkWindow *window = gtk_widget_get_window(widget);
|
||||
|
@ -79,6 +115,7 @@ bool WaylandSurface::attach(GtkWidget *widget)
|
|||
|
||||
gdk_window = window;
|
||||
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
|
||||
gdk_scale = gdk_window_get_scale_factor(gdk_window);
|
||||
|
||||
display = gdk_wayland_display_get_wl_display(gdk_window_get_display(gdk_window));
|
||||
parent = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||
|
@ -98,22 +135,47 @@ bool WaylandSurface::attach(GtkWidget *widget)
|
|||
wl_subsurface_set_desync(subsurface);
|
||||
wl_subsurface_set_position(subsurface, x, y);
|
||||
|
||||
if (fractional_scale_manager)
|
||||
{
|
||||
fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(fractional_scale_manager, child);
|
||||
wp_fractional_scale_v1_add_listener(fractional_scale, &fractional_scale_v1_listener, this);
|
||||
}
|
||||
|
||||
if (idle_inhibit_manager && gui_config->prevent_screensaver)
|
||||
{
|
||||
printf("Inhibiting screensaver.\n");
|
||||
zwp_idle_inhibit_manager_v1_create_inhibitor(idle_inhibit_manager, child);
|
||||
}
|
||||
|
||||
auto scale = gdk_window_get_scale_factor(window);
|
||||
wl_surface_set_buffer_scale(child, scale);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::tuple<int, int> WaylandSurface::get_size()
|
||||
{
|
||||
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
|
||||
|
||||
if (actual_scale == 0.0)
|
||||
{
|
||||
gdk_scale = gdk_window_get_scale_factor(gdk_window);
|
||||
|
||||
return { width * gdk_scale, height * gdk_scale };
|
||||
}
|
||||
|
||||
return { width * actual_scale, height * actual_scale };
|
||||
}
|
||||
|
||||
void WaylandSurface::resize()
|
||||
{
|
||||
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
|
||||
auto scale = gdk_window_get_scale_factor(gdk_window);
|
||||
int w, h; std::tie(w, h) = get_size();
|
||||
wl_subsurface_set_position(subsurface, x, y);
|
||||
wl_surface_set_buffer_scale(child, scale);
|
||||
|
||||
if (!viewport)
|
||||
viewport = wp_viewporter_get_viewport(viewporter, child);
|
||||
|
||||
wp_viewport_set_source(viewport,
|
||||
wl_fixed_from_int(0), wl_fixed_from_int(0),
|
||||
wl_fixed_from_int(w), wl_fixed_from_int(h));
|
||||
wp_viewport_set_destination(viewport, width, height);
|
||||
|
||||
wl_surface_commit(child);
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "gtk_compat.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "fractional-scale-v1.h"
|
||||
|
||||
class WaylandSurface
|
||||
{
|
||||
|
@ -15,6 +17,7 @@ class WaylandSurface
|
|||
~WaylandSurface();
|
||||
bool attach(GtkWidget *widget);
|
||||
void resize();
|
||||
std::tuple<int, int> get_size();
|
||||
|
||||
GdkWindow *gdk_window;
|
||||
|
||||
|
@ -32,7 +35,15 @@ class WaylandSurface
|
|||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int gdk_scale;
|
||||
double actual_scale;
|
||||
|
||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wp_viewport *viewport;
|
||||
|
||||
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
|
||||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue