2022-07-01 23:05:58 +02:00
# include "Hyprpaper.hpp"
2022-09-30 12:18:26 +02:00
CHyprpaper : : CHyprpaper ( ) = default ;
2022-07-01 23:05:58 +02:00
void CHyprpaper : : init ( ) {
2022-07-17 13:59:43 +02:00
removeOldHyprpaperImages ( ) ;
2022-07-01 23:05:58 +02:00
g_pConfigManager = std : : make_unique < CConfigManager > ( ) ;
2022-07-02 18:26:59 +02:00
g_pIPCSocket = std : : make_unique < CIPCSocket > ( ) ;
2022-07-01 23:05:58 +02:00
2022-12-28 23:26:58 +01:00
m_sDisplay = ( wl_display * ) wl_display_connect ( nullptr ) ;
2022-07-01 23:05:58 +02:00
if ( ! m_sDisplay ) {
Debug : : log ( CRIT , " No wayland compositor running! " ) ;
exit ( 1 ) ;
}
preloadAllWallpapersFromConfig ( ) ;
2022-07-31 17:28:37 +02:00
if ( m_bIPCEnabled )
g_pIPCSocket - > initialize ( ) ;
2022-07-02 18:26:59 +02:00
2022-07-01 23:05:58 +02:00
// run
2022-12-28 23:26:58 +01:00
wl_registry * registry = wl_display_get_registry ( m_sDisplay ) ;
2022-07-01 23:05:58 +02:00
wl_registry_add_listener ( registry , & Events : : registryListener , nullptr ) ;
2022-11-02 22:41:32 +01:00
while ( wl_display_dispatch ( m_sDisplay ) ! = - 1 ) {
tick ( true ) ;
2022-07-01 23:05:58 +02:00
}
}
2022-07-31 17:30:14 +02:00
void CHyprpaper : : tick ( bool force ) {
2022-07-31 17:28:37 +02:00
std : : lock_guard < std : : mutex > lg ( m_mtTickMutex ) ;
bool reload = g_pIPCSocket - > mainThreadParseRequest ( ) ;
2022-07-31 17:30:14 +02:00
if ( ! reload & & ! force )
2022-07-31 17:28:37 +02:00
return ;
2022-07-02 18:26:59 +02:00
preloadAllWallpapersFromConfig ( ) ;
2022-07-02 19:10:50 +02:00
ensurePoolBuffersPresent ( ) ;
recheckAllMonitors ( ) ;
2022-07-02 18:26:59 +02:00
}
bool CHyprpaper : : isPreloaded ( const std : : string & path ) {
2022-12-28 23:26:58 +01:00
for ( auto & [ pt , wt ] : m_mWallpaperTargets ) {
2022-07-02 18:26:59 +02:00
if ( pt = = path )
return true ;
}
return false ;
}
2022-07-17 14:17:54 +02:00
void CHyprpaper : : unloadWallpaper ( const std : : string & path ) {
bool found = false ;
for ( auto & [ ewp , cls ] : m_mWallpaperTargets ) {
if ( ewp = = path ) {
// found
found = true ;
break ;
}
}
if ( ! found ) {
Debug : : log ( LOG , " Cannot unload a target that was not loaded! " ) ;
return ;
}
// clean buffers
2022-07-18 12:31:20 +02:00
for ( auto it = m_vBuffers . begin ( ) ; it ! = m_vBuffers . end ( ) ; ) {
2022-07-17 14:17:54 +02:00
2022-07-18 12:31:20 +02:00
if ( it - > get ( ) - > target ! = path ) {
it + + ;
2022-07-17 14:17:54 +02:00
continue ;
2022-07-18 12:31:20 +02:00
}
2022-07-17 14:17:54 +02:00
const auto PRELOADPATH = it - > get ( ) - > name ;
Debug : : log ( LOG , " Unloading target %s, preload path %s " , path . c_str ( ) , PRELOADPATH . c_str ( ) ) ;
std : : filesystem : : remove ( PRELOADPATH ) ;
destroyBuffer ( it - > get ( ) ) ;
it = m_vBuffers . erase ( it ) ;
}
m_mWallpaperTargets . erase ( path ) ; // will free the cairo surface
}
2022-07-01 23:05:58 +02:00
void CHyprpaper : : preloadAllWallpapersFromConfig ( ) {
2022-07-02 18:26:59 +02:00
if ( g_pConfigManager - > m_dRequestedPreloads . empty ( ) )
return ;
2022-07-01 23:05:58 +02:00
for ( auto & wp : g_pConfigManager - > m_dRequestedPreloads ) {
2022-07-07 15:26:38 +02:00
// check if it doesnt exist
bool exists = false ;
2022-12-28 23:26:58 +01:00
for ( auto & [ ewp , cls ] : m_mWallpaperTargets ) {
2022-07-07 15:26:38 +02:00
if ( ewp = = wp ) {
Debug : : log ( LOG , " Ignoring request to preload %s as it already is preloaded! " , ewp . c_str ( ) ) ;
exists = true ;
break ;
}
}
if ( exists )
continue ;
2022-07-01 23:05:58 +02:00
m_mWallpaperTargets [ wp ] = CWallpaperTarget ( ) ;
m_mWallpaperTargets [ wp ] . create ( wp ) ;
}
2022-07-02 18:26:59 +02:00
g_pConfigManager - > m_dRequestedPreloads . clear ( ) ;
2022-07-01 23:05:58 +02:00
}
void CHyprpaper : : recheckAllMonitors ( ) {
for ( auto & m : m_vMonitors ) {
2022-07-02 18:26:59 +02:00
recheckMonitor ( m . get ( ) ) ;
}
}
2022-07-01 23:05:58 +02:00
2022-11-18 21:35:33 +01:00
void CHyprpaper : : createSeat ( wl_seat * pSeat ) {
wl_seat_add_listener ( pSeat , & Events : : seatListener , pSeat ) ;
}
2022-07-02 18:26:59 +02:00
void CHyprpaper : : recheckMonitor ( SMonitor * pMonitor ) {
ensureMonitorHasActiveWallpaper ( pMonitor ) ;
2022-07-01 23:05:58 +02:00
2022-07-02 18:26:59 +02:00
if ( pMonitor - > wantsACK ) {
pMonitor - > wantsACK = false ;
2022-07-02 19:53:12 +02:00
zwlr_layer_surface_v1_ack_configure ( pMonitor - > pCurrentLayerSurface - > pLayerSurface , pMonitor - > configureSerial ) ;
2022-11-18 21:35:33 +01:00
2022-12-28 23:26:58 +01:00
if ( ! pMonitor - > pCurrentLayerSurface - > pCursorImg ) {
int XCURSOR_SIZE = 24 ;
if ( const auto CURSORSIZENV = getenv ( " XCURSOR_SIZE " ) ; CURSORSIZENV ) {
try {
if ( XCURSOR_SIZE = std : : stoi ( CURSORSIZENV ) ; XCURSOR_SIZE < = 0 ) {
throw std : : exception ( ) ;
}
} catch ( . . . ) {
Debug : : log ( WARN , " XCURSOR_SIZE environment variable is set incorrectly " ) ;
XCURSOR_SIZE = 24 ;
2022-12-18 22:27:13 +01:00
}
2022-12-06 07:12:46 +01:00
}
2022-12-28 23:26:58 +01:00
pMonitor - > pCurrentLayerSurface - > pCursorImg = wl_cursor_theme_get_cursor ( wl_cursor_theme_load ( getenv ( " XCURSOR_THEME " ) , XCURSOR_SIZE * pMonitor - > scale , m_sSHM ) , " left_ptr " ) - > images [ 0 ] ;
2022-11-18 21:35:33 +01:00
}
2022-07-02 18:26:59 +02:00
}
if ( pMonitor - > wantsReload ) {
pMonitor - > wantsReload = false ;
renderWallpaperForMonitor ( pMonitor ) ;
}
}
2022-07-17 13:59:43 +02:00
void CHyprpaper : : removeOldHyprpaperImages ( ) {
int cleaned = 0 ;
uint64_t memoryFreed = 0 ;
for ( const auto & entry : std : : filesystem : : directory_iterator ( std : : string ( getenv ( " XDG_RUNTIME_DIR " ) ) ) ) {
if ( entry . is_directory ( ) )
continue ;
const auto FILENAME = entry . path ( ) . filename ( ) . string ( ) ;
if ( FILENAME . contains ( " .hyprpaper_ " ) ) {
// unlink it
memoryFreed + = entry . file_size ( ) ;
2022-07-17 14:12:03 +02:00
if ( ! std : : filesystem : : remove ( entry . path ( ) ) )
Debug : : log ( LOG , " Couldn't remove %s " , entry . path ( ) . string ( ) . c_str ( ) ) ;
2022-07-17 13:59:43 +02:00
cleaned + + ;
}
}
if ( cleaned ! = 0 ) {
Debug : : log ( LOG , " Cleaned old hyprpaper preloads (%i), removing %.1fMB " , cleaned , ( ( float ) memoryFreed ) / 1000000.f ) ;
}
}
2022-07-02 18:26:59 +02:00
SMonitor * CHyprpaper : : getMonitorFromName ( const std : : string & monname ) {
for ( auto & m : m_vMonitors ) {
if ( m - > name = = monname )
return m . get ( ) ;
}
return nullptr ;
}
2022-07-02 19:10:50 +02:00
void CHyprpaper : : ensurePoolBuffersPresent ( ) {
2022-07-03 10:07:43 +02:00
bool anyNewBuffers = false ;
2022-12-28 23:26:58 +01:00
for ( auto & [ file , wt ] : m_mWallpaperTargets ) {
2022-07-02 19:10:50 +02:00
for ( auto & m : m_vMonitors ) {
if ( m - > size = = Vector2D ( ) )
continue ;
2023-01-15 17:13:29 +01:00
auto it = std : : find_if ( m_vBuffers . begin ( ) , m_vBuffers . end ( ) , [ wt = & wt , & m ] ( const std : : unique_ptr < SPoolBuffer > & el ) {
2023-02-18 01:47:40 +01:00
auto scale = std : : round ( ( m - > pCurrentLayerSurface & & m - > pCurrentLayerSurface - > pFractionalScaleInfo ? m - > pCurrentLayerSurface - > fScale : m - > scale ) * 120.0 ) / 120.0 ;
2023-04-09 19:26:11 +02:00
return el - > target = = wt - > m_szPath & & vectorDeltaLessThan ( el - > pixelSize , m - > size * scale , 1 ) ;
2022-07-02 19:10:50 +02:00
} ) ;
if ( it = = m_vBuffers . end ( ) ) {
// create
const auto PBUFFER = m_vBuffers . emplace_back ( std : : make_unique < SPoolBuffer > ( ) ) . get ( ) ;
2023-02-18 01:47:40 +01:00
auto scale = std : : round ( ( m - > pCurrentLayerSurface & & m - > pCurrentLayerSurface - > pFractionalScaleInfo ? m - > pCurrentLayerSurface - > fScale : m - > scale ) * 120.0 ) / 120.0 ;
2023-02-14 21:27:04 +01:00
createBuffer ( PBUFFER , m - > size . x * scale , m - > size . y * scale , WL_SHM_FORMAT_ARGB8888 ) ;
2022-07-02 19:10:50 +02:00
2022-07-18 12:26:13 +02:00
PBUFFER - > target = wt . m_szPath ;
2022-07-03 10:07:43 +02:00
2022-07-18 12:28:56 +02:00
Debug : : log ( LOG , " Buffer created for target %s, Shared Memory usage: %.1fMB " , wt . m_szPath . c_str ( ) , PBUFFER - > size / 1000000.f ) ;
2022-07-03 10:07:43 +02:00
anyNewBuffers = true ;
2022-07-02 19:10:50 +02:00
}
}
}
2022-07-03 10:07:43 +02:00
if ( anyNewBuffers ) {
uint64_t bytesUsed = 0 ;
for ( auto & bf : m_vBuffers ) {
bytesUsed + = bf - > size ;
}
Debug : : log ( LOG , " Total SM usage for all buffers: %.1fMB " , bytesUsed / 1000000.f ) ;
}
2022-07-02 19:10:50 +02:00
}
2022-07-02 18:26:59 +02:00
void CHyprpaper : : clearWallpaperFromMonitor ( const std : : string & monname ) {
const auto PMONITOR = getMonitorFromName ( monname ) ;
if ( ! PMONITOR )
return ;
auto it = m_mMonitorActiveWallpaperTargets . find ( PMONITOR ) ;
if ( it ! = m_mMonitorActiveWallpaperTargets . end ( ) )
m_mMonitorActiveWallpaperTargets . erase ( it ) ;
2022-12-06 07:12:46 +01:00
2022-07-02 19:53:12 +02:00
if ( PMONITOR - > pCurrentLayerSurface ) {
2022-12-06 07:12:46 +01:00
2022-07-02 19:53:12 +02:00
PMONITOR - > pCurrentLayerSurface = nullptr ;
2022-07-02 18:26:59 +02:00
PMONITOR - > wantsACK = false ;
PMONITOR - > wantsReload = false ;
PMONITOR - > initialized = false ;
PMONITOR - > readyForLS = true ;
2022-07-01 23:05:58 +02:00
}
}
void CHyprpaper : : ensureMonitorHasActiveWallpaper ( SMonitor * pMonitor ) {
2022-07-02 15:27:05 +02:00
if ( ! pMonitor - > readyForLS | | ! pMonitor - > hasATarget )
2022-07-01 23:05:58 +02:00
return ;
auto it = m_mMonitorActiveWallpaperTargets . find ( pMonitor ) ;
if ( it = = m_mMonitorActiveWallpaperTargets . end ( ) ) {
m_mMonitorActiveWallpaperTargets [ pMonitor ] = nullptr ;
it = m_mMonitorActiveWallpaperTargets . find ( pMonitor ) ;
}
2022-12-06 07:12:46 +01:00
if ( it - > second )
2022-07-01 23:05:58 +02:00
return ; // has
// get the target
2022-12-28 23:26:58 +01:00
for ( auto & [ mon , path1 ] : m_mMonitorActiveWallpapers ) {
2022-07-01 23:05:58 +02:00
if ( mon = = pMonitor - > name ) {
2022-12-28 23:26:58 +01:00
for ( auto & [ path2 , target ] : m_mWallpaperTargets ) {
2022-07-01 23:05:58 +02:00
if ( path1 = = path2 ) {
it - > second = & target ;
break ;
}
}
break ;
}
}
2022-11-06 23:56:42 +01:00
if ( ! it - > second ) {
// try to find a wildcard
2022-12-28 23:26:58 +01:00
for ( auto & [ mon , path1 ] : m_mMonitorActiveWallpapers ) {
2022-11-06 23:56:42 +01:00
if ( mon . empty ( ) ) {
2022-12-28 23:26:58 +01:00
for ( auto & [ path2 , target ] : m_mWallpaperTargets ) {
2022-11-06 23:56:42 +01:00
if ( path1 = = path2 ) {
it - > second = & target ;
break ;
}
}
break ;
}
}
}
2022-07-01 23:05:58 +02:00
if ( ! it - > second ) {
2022-07-02 15:27:05 +02:00
pMonitor - > hasATarget = false ;
Debug : : log ( WARN , " Monitor %s does not have a target! A wallpaper will not be created. " , pMonitor - > name . c_str ( ) ) ;
2022-07-01 23:05:58 +02:00
return ;
}
2022-07-02 15:27:05 +02:00
2022-07-02 18:26:59 +02:00
// create it for thy if it doesnt have
2022-07-02 19:53:12 +02:00
if ( ! pMonitor - > pCurrentLayerSurface )
2022-07-02 18:26:59 +02:00
createLSForMonitor ( pMonitor ) ;
2022-12-06 07:12:46 +01:00
else
2022-07-02 18:26:59 +02:00
pMonitor - > wantsReload = true ;
2022-07-01 23:05:58 +02:00
}
void CHyprpaper : : createLSForMonitor ( SMonitor * pMonitor ) {
2022-07-02 19:53:12 +02:00
pMonitor - > pCurrentLayerSurface = pMonitor - > layerSurfaces . emplace_back ( std : : make_unique < CLayerSurface > ( pMonitor ) ) . get ( ) ;
2022-07-01 23:05:58 +02:00
}
bool CHyprpaper : : setCloexec ( const int & FD ) {
long flags = fcntl ( FD , F_GETFD ) ;
if ( flags = = - 1 ) {
return false ;
}
if ( fcntl ( FD , F_SETFD , flags | FD_CLOEXEC ) = = - 1 ) {
return false ;
}
return true ;
}
int CHyprpaper : : createPoolFile ( size_t size , std : : string & name ) {
const auto XDGRUNTIMEDIR = getenv ( " XDG_RUNTIME_DIR " ) ;
if ( ! XDGRUNTIMEDIR ) {
Debug : : log ( CRIT , " XDG_RUNTIME_DIR not set! " ) ;
exit ( 1 ) ;
}
name = std : : string ( XDGRUNTIMEDIR ) + " /.hyprpaper_XXXXXX " ;
const auto FD = mkstemp ( ( char * ) name . c_str ( ) ) ;
if ( FD < 0 ) {
Debug : : log ( CRIT , " createPoolFile: fd < 0 " ) ;
exit ( 1 ) ;
}
if ( ! setCloexec ( FD ) ) {
close ( FD ) ;
Debug : : log ( CRIT , " createPoolFile: !setCloexec " ) ;
exit ( 1 ) ;
}
if ( ftruncate ( FD , size ) < 0 ) {
close ( FD ) ;
Debug : : log ( CRIT , " createPoolFile: ftruncate < 0 " ) ;
exit ( 1 ) ;
}
return FD ;
}
void CHyprpaper : : createBuffer ( SPoolBuffer * pBuffer , int32_t w , int32_t h , uint32_t format ) {
2022-12-13 15:27:19 +01:00
const size_t STRIDE = w * 4 ;
2022-07-01 23:05:58 +02:00
const size_t SIZE = STRIDE * h ;
std : : string name ;
const auto FD = createPoolFile ( SIZE , name ) ;
if ( FD = = - 1 ) {
Debug : : log ( CRIT , " Unable to create pool file! " ) ;
exit ( 1 ) ;
}
2022-09-30 12:18:26 +02:00
const auto DATA = mmap ( nullptr , SIZE , PROT_READ | PROT_WRITE , MAP_SHARED , FD , 0 ) ;
2022-07-01 23:05:58 +02:00
const auto POOL = wl_shm_create_pool ( g_pHyprpaper - > m_sSHM , FD , SIZE ) ;
pBuffer - > buffer = wl_shm_pool_create_buffer ( POOL , 0 , w , h , STRIDE , format ) ;
wl_shm_pool_destroy ( POOL ) ;
close ( FD ) ;
pBuffer - > size = SIZE ;
pBuffer - > data = DATA ;
pBuffer - > surface = cairo_image_surface_create_for_data ( ( unsigned char * ) DATA , CAIRO_FORMAT_ARGB32 , w , h , STRIDE ) ;
pBuffer - > cairo = cairo_create ( pBuffer - > surface ) ;
2022-07-02 19:10:50 +02:00
pBuffer - > pixelSize = Vector2D ( w , h ) ;
2022-07-17 14:17:54 +02:00
pBuffer - > name = name ;
2022-07-01 23:05:58 +02:00
}
void CHyprpaper : : destroyBuffer ( SPoolBuffer * pBuffer ) {
wl_buffer_destroy ( pBuffer - > buffer ) ;
cairo_destroy ( pBuffer - > cairo ) ;
cairo_surface_destroy ( pBuffer - > surface ) ;
munmap ( pBuffer - > data , pBuffer - > size ) ;
2022-07-02 18:26:59 +02:00
pBuffer - > buffer = nullptr ;
2022-07-01 23:05:58 +02:00
}
2022-07-02 19:10:50 +02:00
SPoolBuffer * CHyprpaper : : getPoolBuffer ( SMonitor * pMonitor , CWallpaperTarget * pWallpaperTarget ) {
return std : : find_if ( m_vBuffers . begin ( ) , m_vBuffers . end ( ) , [ & ] ( const std : : unique_ptr < SPoolBuffer > & el ) {
2023-02-18 01:47:40 +01:00
auto scale = std : : round ( ( pMonitor - > pCurrentLayerSurface & & pMonitor - > pCurrentLayerSurface - > pFractionalScaleInfo ? pMonitor - > pCurrentLayerSurface - > fScale : pMonitor - > scale ) * 120.0 ) / 120.0 ;
2023-04-09 19:26:11 +02:00
return el - > target = = pWallpaperTarget - > m_szPath & & vectorDeltaLessThan ( el - > pixelSize , pMonitor - > size * scale , 1 ) ;
2022-07-02 19:10:50 +02:00
} ) - > get ( ) ;
}
2022-07-01 23:05:58 +02:00
void CHyprpaper : : renderWallpaperForMonitor ( SMonitor * pMonitor ) {
2022-07-02 19:10:50 +02:00
const auto PWALLPAPERTARGET = m_mMonitorActiveWallpaperTargets [ pMonitor ] ;
2022-08-03 18:06:33 +02:00
const auto CONTAIN = m_mMonitorWallpaperRenderData [ pMonitor - > name ] . contain ;
2022-07-02 18:26:59 +02:00
2022-07-02 19:10:50 +02:00
if ( ! PWALLPAPERTARGET ) {
Debug : : log ( CRIT , " wallpaper target null in render?? " ) ;
exit ( 1 ) ;
2022-07-02 18:26:59 +02:00
}
2022-07-01 23:05:58 +02:00
2022-07-16 22:51:18 +02:00
auto * PBUFFER = getPoolBuffer ( pMonitor , PWALLPAPERTARGET ) ;
if ( ! PBUFFER ) {
Debug : : log ( LOG , " Pool buffer missing for available target?? " ) ;
ensurePoolBuffersPresent ( ) ;
PBUFFER = getPoolBuffer ( pMonitor , PWALLPAPERTARGET ) ;
if ( ! PBUFFER ) {
Debug : : log ( LOG , " Pool buffer failed #2. Ignoring WP. " ) ;
return ;
}
}
2022-07-02 19:10:50 +02:00
2023-02-18 01:47:40 +01:00
const double SURFACESCALE = pMonitor - > pCurrentLayerSurface & & pMonitor - > pCurrentLayerSurface - > pFractionalScaleInfo ? pMonitor - > pCurrentLayerSurface - > fScale : pMonitor - > scale ;
2023-01-29 16:29:53 +01:00
const Vector2D DIMENSIONS = Vector2D { std : : round ( pMonitor - > size . x * SURFACESCALE ) , std : : round ( pMonitor - > size . y * SURFACESCALE ) } ;
2023-01-29 15:00:08 +01:00
2022-07-02 18:26:59 +02:00
const auto PCAIRO = PBUFFER - > cairo ;
2022-07-01 23:05:58 +02:00
cairo_save ( PCAIRO ) ;
cairo_set_operator ( PCAIRO , CAIRO_OPERATOR_CLEAR ) ;
cairo_paint ( PCAIRO ) ;
cairo_restore ( PCAIRO ) ;
2022-08-03 18:06:33 +02:00
if ( CONTAIN ) {
cairo_set_source_rgb ( PCAIRO , 0 , 0 , 0 ) ;
2023-01-29 15:00:08 +01:00
cairo_rectangle ( PCAIRO , 0 , 0 , DIMENSIONS . x , DIMENSIONS . y ) ;
2022-08-03 18:06:33 +02:00
cairo_fill ( PCAIRO ) ;
cairo_surface_flush ( PBUFFER - > surface ) ;
}
2022-07-02 15:09:59 +02:00
// get scale
// we always do cover
float scale ;
Vector2D origin ;
2022-08-03 18:06:33 +02:00
if ( ! CONTAIN ) {
if ( pMonitor - > size . x / pMonitor - > size . y > PWALLPAPERTARGET - > m_vSize . x / PWALLPAPERTARGET - > m_vSize . y ) {
2023-01-29 15:00:08 +01:00
scale = DIMENSIONS . x / PWALLPAPERTARGET - > m_vSize . x ;
2022-07-02 15:09:59 +02:00
2023-01-29 15:00:08 +01:00
origin . y = - ( PWALLPAPERTARGET - > m_vSize . y * scale - DIMENSIONS . y ) / 2.f / scale ;
2022-08-03 18:06:33 +02:00
} else {
2023-01-29 15:00:08 +01:00
scale = DIMENSIONS . y / PWALLPAPERTARGET - > m_vSize . y ;
2022-08-03 18:06:33 +02:00
2023-01-29 15:00:08 +01:00
origin . x = - ( PWALLPAPERTARGET - > m_vSize . x * scale - DIMENSIONS . x ) / 2.f / scale ;
2022-08-03 18:06:33 +02:00
}
2022-07-02 15:09:59 +02:00
} else {
2022-08-03 18:06:33 +02:00
if ( pMonitor - > size . x / pMonitor - > size . y > PWALLPAPERTARGET - > m_vSize . x / PWALLPAPERTARGET - > m_vSize . y ) {
2023-01-29 15:00:08 +01:00
scale = ( DIMENSIONS . y ) / PWALLPAPERTARGET - > m_vSize . y ;
2022-07-02 15:09:59 +02:00
2023-02-18 01:47:40 +01:00
origin . x = ( DIMENSIONS . x - PWALLPAPERTARGET - > m_vSize . x * scale ) / 2.0 / scale ;
2022-08-03 18:06:33 +02:00
} else {
2023-01-29 15:00:08 +01:00
scale = ( DIMENSIONS . x ) / PWALLPAPERTARGET - > m_vSize . x ;
2022-08-03 18:06:33 +02:00
2023-02-18 01:47:40 +01:00
origin . y = ( DIMENSIONS . y - PWALLPAPERTARGET - > m_vSize . y * scale ) / 2.0 / scale ;
2022-08-03 18:06:33 +02:00
}
2022-07-02 15:09:59 +02:00
}
Debug : : log ( LOG , " Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i]) " , pMonitor - > name . c_str ( ) , PWALLPAPERTARGET - > m_szPath . c_str ( ) , origin . x , origin . y , scale , ( int ) PWALLPAPERTARGET - > m_vSize . x , ( int ) PWALLPAPERTARGET - > m_vSize . y ) ;
2023-01-29 16:29:53 +01:00
cairo_scale ( PCAIRO , scale , scale ) ;
2022-07-02 15:09:59 +02:00
cairo_set_source_surface ( PCAIRO , PWALLPAPERTARGET - > m_pCairoSurface , origin . x , origin . y ) ;
2022-07-01 23:05:58 +02:00
cairo_paint ( PCAIRO ) ;
2023-04-09 19:47:49 +02:00
if ( g_pHyprpaper - > m_bRenderSplash & & getenv ( " HYPRLAND_INSTANCE_SIGNATURE " ) ) {
auto SPLASH = execAndGet ( " hyprctl splash " ) ;
SPLASH . pop_back ( ) ;
Debug : : log ( LOG , " Rendering splash: %s " , SPLASH . c_str ( ) ) ;
cairo_select_font_face ( PCAIRO , " Sans " , CAIRO_FONT_SLANT_NORMAL , CAIRO_FONT_WEIGHT_NORMAL ) ;
const auto FONTSIZE = ( int ) ( DIMENSIONS . y / 76.0 / scale ) ;
cairo_set_font_size ( PCAIRO , FONTSIZE ) ;
cairo_set_source_rgba ( PCAIRO , 1.0 , 1.0 , 1.0 , 0.32 ) ;
cairo_text_extents_t textExtents ;
cairo_text_extents ( PCAIRO , SPLASH . c_str ( ) , & textExtents ) ;
cairo_move_to ( PCAIRO , ( ( DIMENSIONS . x - textExtents . width * scale ) / 2.0 ) / scale , ( DIMENSIONS . y * 0.99 - textExtents . height * scale ) / scale ) ;
Debug : : log ( LOG , " Splash font size: %d, pos: %.2f, %.2f " , FONTSIZE , ( DIMENSIONS . x - textExtents . width ) / 2.0 / scale , DIMENSIONS . y * 0.95 - textExtents . height / scale ) ;
cairo_show_text ( PCAIRO , SPLASH . c_str ( ) ) ;
cairo_surface_flush ( PWALLPAPERTARGET - > m_pCairoSurface ) ;
}
2022-07-01 23:05:58 +02:00
cairo_restore ( PCAIRO ) ;
2023-02-18 01:47:40 +01:00
if ( pMonitor - > pCurrentLayerSurface ) {
2023-02-14 21:27:04 +01:00
wl_surface_attach ( pMonitor - > pCurrentLayerSurface - > pSurface , PBUFFER - > buffer , 0 , 0 ) ;
wl_surface_set_buffer_scale ( pMonitor - > pCurrentLayerSurface - > pSurface , pMonitor - > pCurrentLayerSurface - > pFractionalScaleInfo ? 1 : pMonitor - > scale ) ;
wl_surface_damage_buffer ( pMonitor - > pCurrentLayerSurface - > pSurface , 0 , 0 , 0xFFFF , 0xFFFF ) ;
if ( pMonitor - > pCurrentLayerSurface - > pFractionalScaleInfo ) {
Debug : : log ( LOG , " Submitting viewport dest size %ix%i for %x " , static_cast < int > ( std : : round ( pMonitor - > size . x ) ) , static_cast < int > ( std : : round ( pMonitor - > size . y ) ) , pMonitor - > pCurrentLayerSurface ) ;
wp_viewport_set_destination ( pMonitor - > pCurrentLayerSurface - > pViewport , static_cast < int > ( std : : round ( pMonitor - > size . x ) ) , static_cast < int > ( std : : round ( pMonitor - > size . y ) ) ) ;
}
wl_surface_commit ( pMonitor - > pCurrentLayerSurface - > pSurface ) ;
2023-01-29 15:00:08 +01:00
}
2022-07-02 19:53:12 +02:00
// check if we dont need to remove a wallpaper
if ( pMonitor - > layerSurfaces . size ( ) > 1 ) {
for ( auto it = pMonitor - > layerSurfaces . begin ( ) ; it ! = pMonitor - > layerSurfaces . end ( ) ; it + + ) {
if ( pMonitor - > pCurrentLayerSurface ! = it - > get ( ) ) {
pMonitor - > layerSurfaces . erase ( it ) ;
break ;
}
}
}
2022-09-30 12:18:26 +02:00
}