mirror of https://github.com/snes9xgit/snes9x.git
Gtk/Wayland: Different workaround for Gtk damage bug.
Instead of completely shutting down the display driver, shrink the subsurface when removing fullscreen so that when the parent window sends events when it receives damage or is resized.
This commit is contained in:
parent
ea243051ed
commit
0c547f3486
|
@ -145,3 +145,13 @@ void WaylandEGLContext::swap_interval(int frames)
|
|||
{
|
||||
eglSwapInterval(egl_display, frames);
|
||||
}
|
||||
|
||||
void WaylandEGLContext::shrink()
|
||||
{
|
||||
wayland_surface->shrink();
|
||||
}
|
||||
|
||||
void WaylandEGLContext::regrow()
|
||||
{
|
||||
wayland_surface->regrow();
|
||||
}
|
|
@ -26,6 +26,8 @@ class WaylandEGLContext : public OpenGLContext
|
|||
void swap_buffers();
|
||||
void swap_interval(int frames);
|
||||
void make_current();
|
||||
void shrink();
|
||||
void regrow();
|
||||
bool ready();
|
||||
|
||||
EGLDisplay egl_display;
|
||||
|
|
|
@ -23,15 +23,15 @@ static void wl_global(void *data,
|
|||
auto wl = (WaylandSurface *)data;
|
||||
|
||||
if (!strcmp(interface, "wl_compositor"))
|
||||
wl->compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3);
|
||||
wl->compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, version);
|
||||
else if (!strcmp(interface, "wl_subcompositor"))
|
||||
wl->subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
|
||||
wl->subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, version);
|
||||
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);
|
||||
wl->idle_inhibit_manager = (struct zwp_idle_inhibit_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_idle_inhibit_manager_v1_interface, version);
|
||||
else if (!strcmp(interface, wp_viewporter_interface.name))
|
||||
wl->viewporter = (struct wp_viewporter *)wl_registry_bind(wl_registry, name, &wp_viewporter_interface, 1);
|
||||
wl->viewporter = (struct wp_viewporter *)wl_registry_bind(wl_registry, name, &wp_viewporter_interface, version);
|
||||
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);
|
||||
wl->fractional_scale_manager = (struct wp_fractional_scale_manager_v1 *)wl_registry_bind(wl_registry, name, &wp_fractional_scale_manager_v1_interface, version);
|
||||
}
|
||||
|
||||
static void wl_global_remove(void *data,
|
||||
|
@ -161,10 +161,37 @@ std::tuple<int, int> WaylandSurface::get_size_for_metrics(Metrics m)
|
|||
return { round(m.width * actual_scale), round(m.height * actual_scale) };
|
||||
}
|
||||
|
||||
void WaylandSurface::shrink()
|
||||
{
|
||||
if (!viewport)
|
||||
viewport = wp_viewporter_get_viewport(viewporter, child);
|
||||
|
||||
wp_viewport_set_source(viewport,
|
||||
wl_fixed_from_int(-1), wl_fixed_from_int(-1),
|
||||
wl_fixed_from_int(-1), wl_fixed_from_int(-1));
|
||||
wp_viewport_set_destination(viewport, 2, 2);
|
||||
|
||||
wl_surface_commit(child);
|
||||
wl_surface_commit(parent);
|
||||
}
|
||||
|
||||
void WaylandSurface::regrow()
|
||||
{
|
||||
if (!viewport)
|
||||
viewport = wp_viewporter_get_viewport(viewporter, child);
|
||||
|
||||
wp_viewport_set_source(viewport,
|
||||
wl_fixed_from_int(-1), wl_fixed_from_int(-1),
|
||||
wl_fixed_from_int(-1), wl_fixed_from_int(-1));
|
||||
wp_viewport_set_destination(viewport, metrics.width, metrics.height);
|
||||
|
||||
wl_surface_commit(child);
|
||||
wl_surface_commit(parent);
|
||||
}
|
||||
|
||||
void WaylandSurface::resize(Metrics m)
|
||||
{
|
||||
metrics = m;
|
||||
auto [w, h] = get_size();
|
||||
|
||||
wl_subsurface_set_position(subsurface, m.x, m.y);
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ class WaylandSurface
|
|||
|
||||
bool attach(wl_display *display, wl_surface *surface, Metrics source_metrics);
|
||||
void resize(Metrics new_metrics);
|
||||
void shrink();
|
||||
void regrow();
|
||||
std::tuple<int, int> get_size();
|
||||
std::tuple<int, int> get_size_for_metrics(Metrics m);
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ class S9xDisplayDriver
|
|||
virtual bool can_throttle() { return false; };
|
||||
virtual int get_width() = 0;
|
||||
virtual int get_height() = 0;
|
||||
virtual void shrink() {};
|
||||
virtual void regrow() {};
|
||||
|
||||
protected:
|
||||
Snes9xWindow *window;
|
||||
|
|
|
@ -522,3 +522,23 @@ bool S9xOpenGLDisplayDriver::is_ready()
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void S9xOpenGLDisplayDriver::shrink()
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
|
||||
{
|
||||
((WaylandEGLContext *)context)->shrink();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void S9xOpenGLDisplayDriver::regrow()
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
|
||||
{
|
||||
((WaylandEGLContext *)context)->regrow();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
|||
bool can_throttle() override { return true; }
|
||||
int get_width() final override { return output_window_width; }
|
||||
int get_height() final override { return output_window_height; }
|
||||
void shrink() override;
|
||||
void regrow() override;
|
||||
|
||||
private:
|
||||
bool opengl_defaults();
|
||||
|
|
|
@ -253,4 +253,20 @@ void S9xVulkanDisplayDriver::save(const char *filename)
|
|||
bool S9xVulkanDisplayDriver::is_ready()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void S9xVulkanDisplayDriver::shrink()
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
wayland_surface->shrink();
|
||||
#endif
|
||||
}
|
||||
|
||||
void S9xVulkanDisplayDriver::regrow()
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
wayland_surface->regrow();
|
||||
#endif
|
||||
}
|
|
@ -31,6 +31,8 @@ class S9xVulkanDisplayDriver : public S9xDisplayDriver
|
|||
bool can_throttle() override { return true; }
|
||||
int get_width() final override { return current_width; }
|
||||
int get_height() final override { return current_height; }
|
||||
void shrink() override;
|
||||
void regrow() override;
|
||||
|
||||
static int query_availability();
|
||||
|
||||
|
|
|
@ -1144,7 +1144,7 @@ static void set_bypass_compositor(Display *dpy, Window window, unsigned char byp
|
|||
|
||||
void Snes9xWindow::enter_fullscreen_mode()
|
||||
{
|
||||
int rom_loaded = config->rom_loaded;
|
||||
bool rom_loaded = config->rom_loaded;
|
||||
|
||||
if (config->fullscreen)
|
||||
return;
|
||||
|
@ -1152,8 +1152,8 @@ void Snes9xWindow::enter_fullscreen_mode()
|
|||
GdkDisplay *gdk_display = window->get_display()->gobj();
|
||||
GdkWindow *gdk_window = window->get_window()->gobj();
|
||||
|
||||
config->rom_loaded = 0;
|
||||
config->fullscreen = 1;
|
||||
config->rom_loaded = false;
|
||||
config->fullscreen = true;
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (config->change_display_resolution && GDK_IS_X11_WINDOW(gdk_window))
|
||||
|
@ -1232,7 +1232,7 @@ void Snes9xWindow::enter_fullscreen_mode()
|
|||
|
||||
void Snes9xWindow::leave_fullscreen_mode()
|
||||
{
|
||||
int rom_loaded = config->rom_loaded;
|
||||
bool rom_loaded = config->rom_loaded;
|
||||
|
||||
if (!config->fullscreen)
|
||||
return;
|
||||
|
@ -1250,7 +1250,7 @@ void Snes9xWindow::leave_fullscreen_mode()
|
|||
GdkDisplay *gdk_display = window->get_display()->gobj();
|
||||
GdkWindow *gdk_window = window->get_window()->gobj();
|
||||
|
||||
config->rom_loaded = 0;
|
||||
config->rom_loaded = false;
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (config->change_display_resolution && GDK_IS_X11_WINDOW(gdk_window))
|
||||
|
@ -1280,10 +1280,15 @@ void Snes9xWindow::leave_fullscreen_mode()
|
|||
}
|
||||
#endif
|
||||
|
||||
// If the window is covered by a subsurface, for some reason Gtk doesn't
|
||||
// send any resize events or do anything to resize the window. So shrink
|
||||
// the subsurface's viewport to 2x2 temporarily.
|
||||
auto driver = S9xDisplayGetDriver();
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
|
||||
{
|
||||
S9xDeinitDisplay();
|
||||
if (driver)
|
||||
driver->shrink();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1301,14 +1306,15 @@ void Snes9xWindow::leave_fullscreen_mode()
|
|||
#endif
|
||||
|
||||
config->rom_loaded = rom_loaded;
|
||||
config->fullscreen = 0;
|
||||
config->fullscreen = false;
|
||||
configure_widgets();
|
||||
window->show();
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
|
||||
{
|
||||
S9xReinitDisplay();
|
||||
if (driver)
|
||||
driver->regrow();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue