2024-05-03 18:58:40 +02:00
# include "OutputManagement.hpp"
# include <algorithm>
# include "../Compositor.hpp"
2024-07-21 13:09:54 +02:00
using namespace Aquamarine ;
2024-05-03 18:58:40 +02:00
COutputManager : : COutputManager ( SP < CZwlrOutputManagerV1 > resource_ ) : resource ( resource_ ) {
if ( ! good ( ) )
return ;
LOGM ( LOG , " New OutputManager registered " ) ;
resource - > setOnDestroy ( [ this ] ( CZwlrOutputManagerV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setStop ( [ this ] ( CZwlrOutputManagerV1 * r ) { stopped = true ; } ) ;
resource - > setCreateConfiguration ( [ this ] ( CZwlrOutputManagerV1 * r , uint32_t id , uint32_t serial ) {
LOGM ( LOG , " Creating new configuration " ) ;
const auto RESOURCE = PROTO : : outputManagement - > m_vConfigurations . emplace_back (
2024-05-05 18:16:00 +02:00
makeShared < COutputConfiguration > ( makeShared < CZwlrOutputConfigurationV1 > ( resource - > client ( ) , resource - > version ( ) , id ) , self . lock ( ) ) ) ;
2024-05-03 18:58:40 +02:00
if ( ! RESOURCE - > good ( ) ) {
resource - > noMemory ( ) ;
PROTO : : outputManagement - > m_vConfigurations . pop_back ( ) ;
return ;
}
} ) ;
// send all heads at start
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pCompositor - > m_vRealMonitors ) {
2024-10-20 00:03:29 +02:00
if ( m = = g_pCompositor - > m_pUnsafeOutput )
2024-05-03 18:58:40 +02:00
continue ;
LOGM ( LOG , " | sending output head for {} " , m - > szName ) ;
2024-10-20 00:03:29 +02:00
makeAndSendNewHead ( m ) ;
2024-05-03 18:58:40 +02:00
}
sendDone ( ) ;
}
bool COutputManager : : good ( ) {
return resource - > resource ( ) ;
}
2024-10-20 00:03:29 +02:00
void COutputManager : : makeAndSendNewHead ( PHLMONITOR pMonitor ) {
2024-05-03 18:58:40 +02:00
if ( stopped )
return ;
const auto RESOURCE =
2024-05-05 18:16:00 +02:00
PROTO : : outputManagement - > m_vHeads . emplace_back ( makeShared < COutputHead > ( makeShared < CZwlrOutputHeadV1 > ( resource - > client ( ) , resource - > version ( ) , 0 ) , pMonitor ) ) ;
2024-05-03 18:58:40 +02:00
if ( ! RESOURCE - > good ( ) ) {
resource - > noMemory ( ) ;
PROTO : : outputManagement - > m_vHeads . pop_back ( ) ;
return ;
}
heads . push_back ( RESOURCE ) ;
resource - > sendHead ( RESOURCE - > resource . get ( ) ) ;
RESOURCE - > sendAllData ( ) ;
}
2024-10-20 00:03:29 +02:00
void COutputManager : : ensureMonitorSent ( PHLMONITOR pMonitor ) {
2024-05-03 18:58:40 +02:00
if ( pMonitor = = g_pCompositor - > m_pUnsafeOutput )
return ;
2024-08-26 20:24:30 +02:00
for ( auto const & hw : heads ) {
2024-05-03 18:58:40 +02:00
auto h = hw . lock ( ) ;
if ( ! h )
continue ;
if ( h - > pMonitor = = pMonitor )
return ;
}
makeAndSendNewHead ( pMonitor ) ;
sendDone ( ) ;
}
void COutputManager : : sendDone ( ) {
resource - > sendDone ( wl_display_next_serial ( g_pCompositor - > m_sWLDisplay ) ) ;
}
2024-10-20 00:03:29 +02:00
COutputHead : : COutputHead ( SP < CZwlrOutputHeadV1 > resource_ , PHLMONITOR pMonitor_ ) : resource ( resource_ ) , pMonitor ( pMonitor_ ) {
2024-05-03 18:58:40 +02:00
if ( ! good ( ) )
return ;
resource - > setRelease ( [ this ] ( CZwlrOutputHeadV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setOnDestroy ( [ this ] ( CZwlrOutputHeadV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
listeners . monitorDestroy = pMonitor - > events . destroy . registerListener ( [ this ] ( std : : any d ) {
resource - > sendFinished ( ) ;
2024-08-26 20:24:30 +02:00
for ( auto const & mw : modes ) {
2024-05-03 18:58:40 +02:00
auto m = mw . lock ( ) ;
if ( ! m )
continue ;
m - > resource - > sendFinished ( ) ;
}
2024-10-20 00:03:29 +02:00
pMonitor . reset ( ) ;
2024-08-26 20:24:30 +02:00
for ( auto const & m : PROTO : : outputManagement - > m_vManagers ) {
2024-05-23 21:15:31 +02:00
m - > sendDone ( ) ;
}
2024-05-03 18:58:40 +02:00
} ) ;
listeners . monitorModeChange = pMonitor - > events . modeChanged . registerListener ( [ this ] ( std : : any d ) { updateMode ( ) ; } ) ;
}
bool COutputHead : : good ( ) {
return resource - > resource ( ) ;
}
void COutputHead : : sendAllData ( ) {
const auto VERSION = resource - > version ( ) ;
resource - > sendName ( pMonitor - > szName . c_str ( ) ) ;
resource - > sendDescription ( pMonitor - > szDescription . c_str ( ) ) ;
2024-07-21 13:09:54 +02:00
if ( pMonitor - > output - > physicalSize . x > 0 & & pMonitor - > output - > physicalSize . y > 0 )
resource - > sendPhysicalSize ( pMonitor - > output - > physicalSize . x , pMonitor - > output - > physicalSize . y ) ;
2024-05-03 18:58:40 +02:00
resource - > sendEnabled ( pMonitor - > m_bEnabled ) ;
if ( pMonitor - > m_bEnabled ) {
resource - > sendPosition ( pMonitor - > vecPosition . x , pMonitor - > vecPosition . y ) ;
resource - > sendTransform ( pMonitor - > transform ) ;
resource - > sendScale ( wl_fixed_from_double ( pMonitor - > scale ) ) ;
}
2024-07-21 13:09:54 +02:00
if ( ! pMonitor - > output - > make . empty ( ) & & VERSION > = 2 )
resource - > sendMake ( pMonitor - > output - > make . c_str ( ) ) ;
if ( ! pMonitor - > output - > model . empty ( ) & & VERSION > = 2 )
resource - > sendModel ( pMonitor - > output - > model . c_str ( ) ) ;
if ( ! pMonitor - > output - > serial . empty ( ) & & VERSION > = 2 )
resource - > sendSerialNumber ( pMonitor - > output - > serial . c_str ( ) ) ;
2024-05-03 18:58:40 +02:00
if ( VERSION > = 4 )
resource - > sendAdaptiveSync ( pMonitor - > vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED ) ;
// send all available modes
if ( modes . empty ( ) ) {
2024-07-21 13:09:54 +02:00
if ( ! pMonitor - > output - > modes . empty ( ) ) {
2024-08-26 20:24:30 +02:00
for ( auto const & m : pMonitor - > output - > modes ) {
2024-07-21 13:09:54 +02:00
makeAndSendNewMode ( m ) ;
2024-05-03 18:58:40 +02:00
}
2024-07-21 13:09:54 +02:00
} else if ( pMonitor - > output - > state - > state ( ) . customMode ) {
makeAndSendNewMode ( pMonitor - > output - > state - > state ( ) . customMode ) ;
2024-05-03 18:58:40 +02:00
} else
makeAndSendNewMode ( nullptr ) ;
}
// send current mode
if ( pMonitor - > m_bEnabled ) {
2024-08-26 20:24:30 +02:00
for ( auto const & mw : modes ) {
2024-05-03 18:58:40 +02:00
auto m = mw . lock ( ) ;
if ( ! m )
continue ;
2024-07-21 13:09:54 +02:00
if ( m - > mode = = pMonitor - > output - > state - > state ( ) . mode ) {
2024-05-03 18:58:40 +02:00
if ( m - > mode )
2024-07-21 13:09:54 +02:00
LOGM ( LOG , " | sending current mode for {}: {}x{}@{} " , pMonitor - > szName , m - > mode - > pixelSize . x , m - > mode - > pixelSize . y , m - > mode - > refreshRate ) ;
2024-05-03 18:58:40 +02:00
else
LOGM ( LOG , " | sending current mode for {}: null (fake) " , pMonitor - > szName ) ;
2024-05-07 15:26:26 +02:00
resource - > sendCurrentMode ( m - > resource . get ( ) ) ;
2024-05-03 18:58:40 +02:00
break ;
}
}
}
}
void COutputHead : : updateMode ( ) {
resource - > sendEnabled ( pMonitor - > m_bEnabled ) ;
if ( pMonitor - > m_bEnabled ) {
resource - > sendPosition ( pMonitor - > vecPosition . x , pMonitor - > vecPosition . y ) ;
resource - > sendTransform ( pMonitor - > transform ) ;
resource - > sendScale ( wl_fixed_from_double ( pMonitor - > scale ) ) ;
}
if ( resource - > version ( ) > = 4 )
resource - > sendAdaptiveSync ( pMonitor - > vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED ) ;
if ( pMonitor - > m_bEnabled ) {
2024-08-26 20:24:30 +02:00
for ( auto const & mw : modes ) {
2024-05-03 18:58:40 +02:00
auto m = mw . lock ( ) ;
if ( ! m )
continue ;
if ( m - > mode = = pMonitor - > currentMode ) {
if ( m - > mode )
2024-07-21 13:09:54 +02:00
LOGM ( LOG , " | sending current mode for {}: {}x{}@{} " , pMonitor - > szName , m - > mode - > pixelSize . x , m - > mode - > pixelSize . y , m - > mode - > refreshRate ) ;
2024-05-03 18:58:40 +02:00
else
LOGM ( LOG , " | sending current mode for {}: null (fake) " , pMonitor - > szName ) ;
2024-05-07 15:26:26 +02:00
resource - > sendCurrentMode ( m - > resource . get ( ) ) ;
2024-05-03 18:58:40 +02:00
break ;
}
}
}
}
2024-07-21 13:09:54 +02:00
void COutputHead : : makeAndSendNewMode ( SP < Aquamarine : : SOutputMode > mode ) {
2024-05-05 18:16:00 +02:00
const auto RESOURCE = PROTO : : outputManagement - > m_vModes . emplace_back ( makeShared < COutputMode > ( makeShared < CZwlrOutputModeV1 > ( resource - > client ( ) , resource - > version ( ) , 0 ) , mode ) ) ;
2024-05-03 18:58:40 +02:00
if ( ! RESOURCE - > good ( ) ) {
resource - > noMemory ( ) ;
PROTO : : outputManagement - > m_vModes . pop_back ( ) ;
return ;
}
modes . push_back ( RESOURCE ) ;
resource - > sendMode ( RESOURCE - > resource . get ( ) ) ;
RESOURCE - > sendAllData ( ) ;
}
2024-10-20 00:03:29 +02:00
PHLMONITOR COutputHead : : monitor ( ) {
return pMonitor . lock ( ) ;
2024-05-03 18:58:40 +02:00
}
2024-07-21 13:09:54 +02:00
COutputMode : : COutputMode ( SP < CZwlrOutputModeV1 > resource_ , SP < Aquamarine : : SOutputMode > mode_ ) : resource ( resource_ ) , mode ( mode_ ) {
2024-05-03 18:58:40 +02:00
if ( ! good ( ) )
return ;
resource - > setRelease ( [ this ] ( CZwlrOutputModeV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setOnDestroy ( [ this ] ( CZwlrOutputModeV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
}
void COutputMode : : sendAllData ( ) {
if ( ! mode )
return ;
2024-07-21 13:09:54 +02:00
LOGM ( LOG , " | sending mode {}x{}@{}mHz, pref: {} " , mode - > pixelSize . x , mode - > pixelSize . y , mode - > refreshRate , mode - > preferred ) ;
2024-05-03 18:58:40 +02:00
2024-07-21 13:09:54 +02:00
resource - > sendSize ( mode - > pixelSize . x , mode - > pixelSize . y ) ;
if ( mode - > refreshRate > 0 )
resource - > sendRefresh ( mode - > refreshRate ) ;
2024-05-03 18:58:40 +02:00
if ( mode - > preferred )
resource - > sendPreferred ( ) ;
}
bool COutputMode : : good ( ) {
return resource - > resource ( ) ;
}
2024-07-21 13:09:54 +02:00
SP < Aquamarine : : SOutputMode > COutputMode : : getMode ( ) {
return mode . lock ( ) ;
2024-05-03 18:58:40 +02:00
}
COutputConfiguration : : COutputConfiguration ( SP < CZwlrOutputConfigurationV1 > resource_ , SP < COutputManager > owner_ ) : resource ( resource_ ) , owner ( owner_ ) {
if ( ! good ( ) )
return ;
resource - > setDestroy ( [ this ] ( CZwlrOutputConfigurationV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setOnDestroy ( [ this ] ( CZwlrOutputConfigurationV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setEnableHead ( [ this ] ( CZwlrOutputConfigurationV1 * r , uint32_t id , wl_resource * outputHead ) {
const auto HEAD = PROTO : : outputManagement - > headFromResource ( outputHead ) ;
if ( ! HEAD ) {
LOGM ( ERR , " No head in setEnableHead?? " ) ;
return ;
}
const auto PMONITOR = HEAD - > monitor ( ) ;
if ( ! PMONITOR ) {
LOGM ( ERR , " No monitor in setEnableHead?? " ) ;
return ;
}
const auto RESOURCE = PROTO : : outputManagement - > m_vConfigurationHeads . emplace_back (
2024-05-05 18:16:00 +02:00
makeShared < COutputConfigurationHead > ( makeShared < CZwlrOutputConfigurationHeadV1 > ( resource - > client ( ) , resource - > version ( ) , id ) , PMONITOR ) ) ;
2024-05-03 18:58:40 +02:00
if ( ! RESOURCE - > good ( ) ) {
resource - > noMemory ( ) ;
PROTO : : outputManagement - > m_vConfigurationHeads . pop_back ( ) ;
return ;
}
heads . push_back ( RESOURCE ) ;
LOGM ( LOG , " enableHead on {}. For now, doing nothing. Waiting for apply(). " , PMONITOR - > szName ) ;
} ) ;
resource - > setDisableHead ( [ this ] ( CZwlrOutputConfigurationV1 * r , wl_resource * outputHead ) {
const auto HEAD = PROTO : : outputManagement - > headFromResource ( outputHead ) ;
if ( ! HEAD ) {
LOGM ( ERR , " No head in setDisableHead?? " ) ;
return ;
}
const auto PMONITOR = HEAD - > monitor ( ) ;
if ( ! PMONITOR ) {
LOGM ( ERR , " No monitor in setDisableHead?? " ) ;
return ;
}
LOGM ( LOG , " disableHead on {} " , PMONITOR - > szName ) ;
2024-09-26 12:10:53 +02:00
SWlrManagerSavedOutputState newState ;
if ( owner - > monitorStates . contains ( PMONITOR - > szName ) )
newState = owner - > monitorStates . at ( PMONITOR - > szName ) ;
newState . enabled = false ;
g_pConfigManager - > m_bWantsMonitorReload = true ;
owner - > monitorStates [ PMONITOR - > szName ] = newState ;
2024-05-03 18:58:40 +02:00
} ) ;
resource - > setTest ( [ this ] ( CZwlrOutputConfigurationV1 * r ) {
const auto SUCCESS = applyTestConfiguration ( true ) ;
if ( SUCCESS )
resource - > sendSucceeded ( ) ;
else
resource - > sendFailed ( ) ;
} ) ;
resource - > setApply ( [ this ] ( CZwlrOutputConfigurationV1 * r ) {
const auto SUCCESS = applyTestConfiguration ( false ) ;
if ( SUCCESS )
resource - > sendSucceeded ( ) ;
else
resource - > sendFailed ( ) ;
2024-05-05 18:16:00 +02:00
owner - > sendDone ( ) ;
2024-05-03 18:58:40 +02:00
} ) ;
}
bool COutputConfiguration : : good ( ) {
return resource - > resource ( ) ;
}
bool COutputConfiguration : : applyTestConfiguration ( bool test ) {
if ( test ) {
LOGM ( WARN , " TODO: STUB: applyTestConfiguration for test not implemented, returning true. " ) ;
return true ;
}
LOGM ( LOG , " Applying configuration " ) ;
2024-09-26 12:10:53 +02:00
if ( ! owner ) {
LOGM ( ERR , " applyTestConfiguration: no owner?! " ) ;
return false ;
}
2024-08-26 20:24:30 +02:00
for ( auto const & headw : heads ) {
2024-05-03 18:58:40 +02:00
auto head = headw . lock ( ) ;
if ( ! head )
continue ;
const auto PMONITOR = head - > pMonitor ;
if ( ! PMONITOR )
continue ;
2024-09-26 12:10:53 +02:00
LOGM ( LOG , " Saving config for monitor {} " , PMONITOR - > szName ) ;
SWlrManagerSavedOutputState newState ;
if ( owner - > monitorStates . contains ( PMONITOR - > szName ) )
newState = owner - > monitorStates . at ( PMONITOR - > szName ) ;
2024-05-03 18:58:40 +02:00
2024-09-26 12:10:53 +02:00
newState . enabled = true ;
2024-05-03 18:58:40 +02:00
2024-09-26 12:10:53 +02:00
if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_MODE ) {
newState . resolution = head - > state . mode - > getMode ( ) - > pixelSize ;
newState . refresh = head - > state . mode - > getMode ( ) - > refreshRate ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_MODE ;
LOGM ( LOG , " > Mode: {:.0f}x{:.0f}@{}mHz " , newState . resolution . x , newState . resolution . y , newState . refresh ) ;
} else if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_CUSTOM_MODE ) {
newState . resolution = head - > state . customMode . size ;
newState . refresh = head - > state . customMode . refresh ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_CUSTOM_MODE ;
LOGM ( LOG , " > Custom mode: {:.0f}x{:.0f}@{}mHz " , newState . resolution . x , newState . resolution . y , newState . refresh ) ;
2024-05-03 18:58:40 +02:00
}
2024-09-26 12:10:53 +02:00
if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_POSITION ) {
newState . position = head - > state . position ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_POSITION ;
LOGM ( LOG , " > Position: {:.0f}, {:.0f} " , head - > state . position . x , head - > state . position . y ) ;
}
2024-05-03 18:58:40 +02:00
2024-09-26 12:10:53 +02:00
if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC ) {
newState . adaptiveSync = head - > state . adaptiveSync ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC ;
LOGM ( LOG , " > vrr: {} " , newState . adaptiveSync ) ;
}
2024-05-03 18:58:40 +02:00
2024-09-26 12:10:53 +02:00
if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_SCALE ) {
newState . scale = head - > state . scale ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_SCALE ;
LOGM ( LOG , " > scale: {:.2f} " , newState . scale ) ;
}
2024-05-03 18:58:40 +02:00
2024-09-26 12:10:53 +02:00
if ( head - > state . committedProperties & eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_TRANSFORM ) {
newState . transform = head - > state . transform ;
newState . committedProperties | = eWlrOutputCommittedProperties : : OUTPUT_HEAD_COMMITTED_TRANSFORM ;
LOGM ( LOG , " > transform: {} " , ( uint8_t ) newState . transform ) ;
}
2024-05-03 18:58:40 +02:00
// reset properties for next set.
2024-09-26 12:10:53 +02:00
head - > state . committedProperties = 0 ;
2024-05-03 18:58:40 +02:00
g_pConfigManager - > m_bWantsMonitorReload = true ;
2024-09-26 12:10:53 +02:00
owner - > monitorStates [ PMONITOR - > szName ] = newState ;
2024-05-03 18:58:40 +02:00
}
2024-09-26 12:10:53 +02:00
LOGM ( LOG , " Saved configuration " ) ;
2024-05-03 18:58:40 +02:00
return true ;
}
2024-10-20 00:03:29 +02:00
COutputConfigurationHead : : COutputConfigurationHead ( SP < CZwlrOutputConfigurationHeadV1 > resource_ , PHLMONITOR pMonitor_ ) : resource ( resource_ ) , pMonitor ( pMonitor_ ) {
2024-05-03 18:58:40 +02:00
if ( ! good ( ) )
return ;
resource - > setOnDestroy ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r ) { PROTO : : outputManagement - > destroyResource ( this ) ; } ) ;
resource - > setSetMode ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , wl_resource * outputMode ) {
const auto MODE = PROTO : : outputManagement - > modeFromResource ( outputMode ) ;
if ( ! MODE | | ! MODE - > getMode ( ) ) {
LOGM ( ERR , " No mode in setMode?? " ) ;
return ;
}
if ( ! pMonitor ) {
LOGM ( ERR , " setMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_MODE ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_MODE ;
2024-05-03 18:58:40 +02:00
state . mode = MODE ;
2024-07-21 13:09:54 +02:00
LOGM ( LOG , " | configHead for {}: set mode to {}x{}@{} " , pMonitor - > szName , MODE - > getMode ( ) - > pixelSize . x , MODE - > getMode ( ) - > pixelSize . y , MODE - > getMode ( ) - > refreshRate ) ;
2024-05-03 18:58:40 +02:00
} ) ;
resource - > setSetCustomMode ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , int32_t w , int32_t h , int32_t refresh ) {
if ( ! pMonitor ) {
LOGM ( ERR , " setCustomMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
2024-09-30 18:40:38 +02:00
if ( w < = 0 | | h < = 0 | | refresh < 0 ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_CUSTOM_MODE , " Invalid mode " ) ;
return ;
}
2024-09-30 18:40:38 +02:00
if ( refresh = = 0 ) {
LOGM ( LOG , " | configHead for {}: refreshRate 0, using old refresh rate of {:.2f}Hz " , pMonitor - > szName , pMonitor - > refreshRate ) ;
refresh = std : : round ( pMonitor - > refreshRate * 1000.F ) ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_CUSTOM_MODE ;
2024-05-03 18:58:40 +02:00
state . customMode = { { w , h } , ( uint32_t ) refresh } ;
LOGM ( LOG , " | configHead for {}: set custom mode to {}x{}@{} " , pMonitor - > szName , w , h , refresh ) ;
} ) ;
resource - > setSetPosition ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , int32_t x , int32_t y ) {
if ( ! pMonitor ) {
LOGM ( ERR , " setMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_POSITION ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_POSITION ;
2024-05-03 18:58:40 +02:00
state . position = { x , y } ;
LOGM ( LOG , " | configHead for {}: set pos to {}, {} " , pMonitor - > szName , x , y ) ;
} ) ;
resource - > setSetTransform ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , int32_t transform ) {
if ( ! pMonitor ) {
LOGM ( ERR , " setMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
if ( transform < 0 | | transform > 7 ) {
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_TRANSFORM , " Invalid transform " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_TRANSFORM ;
2024-05-03 18:58:40 +02:00
state . transform = ( wl_output_transform ) transform ;
LOGM ( LOG , " | configHead for {}: set transform to {} " , pMonitor - > szName , transform ) ;
} ) ;
resource - > setSetScale ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , wl_fixed_t scale_ ) {
if ( ! pMonitor ) {
LOGM ( ERR , " setMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_SCALE ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
double scale = wl_fixed_to_double ( scale_ ) ;
if ( scale < 0.1 | | scale > 10.0 ) {
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_SCALE , " Invalid scale " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_SCALE ;
2024-05-03 18:58:40 +02:00
state . scale = scale ;
LOGM ( LOG , " | configHead for {}: set scale to {:.2f} " , pMonitor - > szName , scale ) ;
} ) ;
resource - > setSetAdaptiveSync ( [ this ] ( CZwlrOutputConfigurationHeadV1 * r , uint32_t as ) {
if ( ! pMonitor ) {
LOGM ( ERR , " setMode on inert resource " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
if ( state . committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC ) {
2024-05-03 18:58:40 +02:00
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET , " Property already set " ) ;
return ;
}
if ( as > 1 ) {
resource - > error ( ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_ADAPTIVE_SYNC_STATE , " Invalid adaptive sync state " ) ;
return ;
}
2024-09-26 12:10:53 +02:00
state . committedProperties | = OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC ;
2024-05-03 18:58:40 +02:00
state . adaptiveSync = as ;
LOGM ( LOG , " | configHead for {}: set adaptiveSync to {} " , pMonitor - > szName , as ) ;
} ) ;
}
bool COutputConfigurationHead : : good ( ) {
return resource - > resource ( ) ;
}
COutputManagementProtocol : : COutputManagementProtocol ( const wl_interface * iface , const int & ver , const std : : string & name ) : IWaylandProtocol ( iface , ver , name ) {
static auto P = g_pHookSystem - > hookDynamic ( " monitorLayoutChanged " , [ this ] ( void * self , SCallbackInfo & info , std : : any param ) { this - > updateAllOutputs ( ) ; } ) ;
}
void COutputManagementProtocol : : bindManager ( wl_client * client , void * data , uint32_t ver , uint32_t id ) {
2024-05-05 18:16:00 +02:00
const auto RESOURCE = m_vManagers . emplace_back ( makeShared < COutputManager > ( makeShared < CZwlrOutputManagerV1 > ( client , ver , id ) ) ) ;
2024-05-03 18:58:40 +02:00
if ( ! RESOURCE - > good ( ) ) {
wl_client_post_no_memory ( client ) ;
m_vManagers . pop_back ( ) ;
return ;
}
RESOURCE - > self = RESOURCE ;
}
void COutputManagementProtocol : : destroyResource ( COutputManager * resource ) {
std : : erase_if ( m_vManagers , [ & ] ( const auto & other ) { return other . get ( ) = = resource ; } ) ;
}
void COutputManagementProtocol : : destroyResource ( COutputHead * resource ) {
std : : erase_if ( m_vHeads , [ & ] ( const auto & other ) { return other . get ( ) = = resource ; } ) ;
}
void COutputManagementProtocol : : destroyResource ( COutputMode * resource ) {
std : : erase_if ( m_vModes , [ & ] ( const auto & other ) { return other . get ( ) = = resource ; } ) ;
}
void COutputManagementProtocol : : destroyResource ( COutputConfiguration * resource ) {
std : : erase_if ( m_vConfigurations , [ & ] ( const auto & other ) { return other . get ( ) = = resource ; } ) ;
}
void COutputManagementProtocol : : destroyResource ( COutputConfigurationHead * resource ) {
std : : erase_if ( m_vConfigurationHeads , [ & ] ( const auto & other ) { return other . get ( ) = = resource ; } ) ;
}
void COutputManagementProtocol : : updateAllOutputs ( ) {
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pCompositor - > m_vRealMonitors ) {
for ( auto const & mgr : m_vManagers ) {
2024-10-20 00:03:29 +02:00
mgr - > ensureMonitorSent ( m ) ;
2024-05-03 18:58:40 +02:00
}
}
}
SP < COutputHead > COutputManagementProtocol : : headFromResource ( wl_resource * r ) {
2024-08-26 20:24:30 +02:00
for ( auto const & h : m_vHeads ) {
2024-05-03 18:58:40 +02:00
if ( h - > resource - > resource ( ) = = r )
return h ;
}
return nullptr ;
}
SP < COutputMode > COutputManagementProtocol : : modeFromResource ( wl_resource * r ) {
2024-08-26 20:24:30 +02:00
for ( auto const & h : m_vModes ) {
2024-05-03 18:58:40 +02:00
if ( h - > resource - > resource ( ) = = r )
return h ;
}
return nullptr ;
}
2024-09-26 12:10:53 +02:00
SP < SWlrManagerSavedOutputState > COutputManagementProtocol : : getOutputStateFor ( SP < CMonitor > pMonitor ) {
for ( auto const & m : m_vManagers ) {
if ( ! m - > monitorStates . contains ( pMonitor - > szName ) )
continue ;
return makeShared < SWlrManagerSavedOutputState > ( m - > monitorStates . at ( pMonitor - > szName ) ) ;
}
return nullptr ;
}