From bf3bd28bfa4c07ca816c5876b7d2c5f4c01e7684 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Wed, 24 Jan 2024 12:19:52 +0400 Subject: [PATCH] wayland: Keep track of entered outputs for scale Wayland kindly informs us which outputs the surface is on, to be used for scale computation (at least on wl_compositor < 6). On mixed DPI setups this fixes Tracy potentially using a higher scale than the output it's displayed on. However, as is, this commit results in Tracy always using scale 1, because at the point of backend creation (which is when the scale is queried) the surface is not yet displayed on any outputs, so a scale of 1 is assumed. --- profiler/src/BackendWayland.cpp | 53 ++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/profiler/src/BackendWayland.cpp b/profiler/src/BackendWayland.cpp index feea6379..c33382e4 100644 --- a/profiler/src/BackendWayland.cpp +++ b/profiler/src/BackendWayland.cpp @@ -194,6 +194,7 @@ struct Output { int32_t scale; wl_output* obj; + bool entered; }; static std::unordered_map> s_output; static int s_maxScale = 1; @@ -207,6 +208,16 @@ static uint64_t s_time; static wl_fixed_t s_wheelAxisX, s_wheelAxisY; static bool s_wheel; +static void RecomputeScale() +{ + int max = 1; + for( auto& out : s_output ) + { + if( out.second->entered && out.second->scale > max ) max = out.second->scale; + } + s_maxScale = max; +} + static void PointerEnter( void*, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surf, wl_fixed_t sx, wl_fixed_t sy ) { wl_pointer_set_cursor( pointer, serial, s_cursorSurf, s_cursorX, s_cursorY ); @@ -471,12 +482,7 @@ static void OutputMode( void*, struct wl_output* output, uint32_t flags, int32_t static void OutputDone( void*, struct wl_output* output ) { - int max = 1; - for( auto& out : s_output ) - { - if( out.second->scale > max ) max = out.second->scale; - } - s_maxScale = max; + RecomputeScale(); } static void OutputScale( void* data, struct wl_output* output, int32_t scale ) @@ -529,7 +535,7 @@ static void RegistryGlobal( void*, struct wl_registry* reg, uint32_t name, const else if( strcmp( interface, wl_output_interface.name ) == 0 ) { auto output = (wl_output*)wl_registry_bind( reg, name, &wl_output_interface, 2 ); - auto ptr = std::make_unique( Output { 1, output } ); + auto ptr = std::make_unique( Output { 1, output, false } ); wl_output_add_listener( output, &outputListener, ptr.get() ); s_output.emplace( name, std::move( ptr ) ); } @@ -545,6 +551,7 @@ static void RegistryGlobalRemove( void*, struct wl_registry* reg, uint32_t name if( it == s_output.end() ) return; wl_output_destroy( it->second->obj ); s_output.erase( it ); + RecomputeScale(); } constexpr struct wl_registry_listener registryListener = { @@ -603,6 +610,37 @@ constexpr struct xdg_toplevel_listener toplevelListener = { .close = XdgToplevelClose }; +static void SurfaceEnter( void*, struct wl_surface* surface, struct wl_output* output ) +{ + for ( auto& out : s_output ) + { + if ( out.second->obj == output ) + { + out.second->entered = true; + RecomputeScale(); + break; + } + } +} + +static void SurfaceLeave( void*, struct wl_surface* surface, struct wl_output* output ) +{ + for ( auto& out : s_output ) + { + if ( out.second->obj == output ) + { + out.second->entered = false; + RecomputeScale(); + break; + } + } +} + +constexpr struct wl_surface_listener surfaceListener = { + .enter = SurfaceEnter, + .leave = SurfaceLeave, +}; + static void SetupCursor() { auto env_xcursor_theme = getenv( "XCURSOR_THEME" ); @@ -645,6 +683,7 @@ Backend::Backend( const char* title, const std::function& redraw, RunQue if( !s_seat ) { fprintf( stderr, "No wayland seat!\n" ); exit( 1 ); } s_surf = wl_compositor_create_surface( s_comp ); + wl_surface_add_listener( s_surf, &surfaceListener, nullptr ); s_eglWin = wl_egl_window_create( s_surf, m_winPos.w, m_winPos.h ); s_xdgSurf = xdg_wm_base_get_xdg_surface( s_wm, s_surf ); xdg_surface_add_listener( s_xdgSurf, &xdgSurfaceListener, nullptr );