2022-03-21 15:17:04 +01:00
# include "../Compositor.hpp"
# include "../helpers/WLClasses.hpp"
2022-06-09 12:46:55 +02:00
# include "../managers/input/InputManager.hpp"
2022-03-21 15:17:04 +01:00
# include "../render/Renderer.hpp"
# include "Events.hpp"
2022-04-21 22:00:03 +02:00
# include "../debug/HyprCtl.hpp"
2022-03-21 15:17:04 +01:00
// --------------------------------------------------------- //
// __ __ ____ _ _ _____ _______ ____ _____ _____ //
// | \/ |/ __ \| \ | |_ _|__ __/ __ \| __ \ / ____| //
// | \ / | | | | \| | | | | | | | | | |__) | (___ //
// | |\/| | | | | . ` | | | | | | | | | _ / \___ \ //
// | | | | |__| | |\ |_| |_ | | | |__| | | \ \ ____) | //
// |_| |_|\____/|_| \_|_____| |_| \____/|_| \_\_____/ //
// //
// --------------------------------------------------------- //
2022-07-27 12:32:00 +02:00
CMonitor * pMostHzMonitor = nullptr ;
2022-07-12 10:02:12 +02:00
2022-06-17 20:31:15 +02:00
void Events : : listener_change ( wl_listener * listener , void * data ) {
2022-03-21 15:17:04 +01:00
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create ( ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create ( CONFIG , m - > output ) ;
2022-03-21 15:17:04 +01:00
// TODO: clients off of disabled
wlr_box BOX ;
2022-06-30 15:44:26 +02:00
wlr_output_layout_get_box ( g_pCompositor - > m_sWLROutputLayout , m - > output , & BOX ) ;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
m - > vecPosition . x = BOX . x ;
m - > vecPosition . y = BOX . y ;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
CONFIGHEAD - > state . enabled = m - > output - > enabled ;
CONFIGHEAD - > state . mode = m - > output - > current_mode ;
CONFIGHEAD - > state . x = m - > vecPosition . x ;
CONFIGHEAD - > state . y = m - > vecPosition . y ;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
wlr_output_set_custom_mode ( m - > output , m - > vecPixelSize . x , m - > vecPixelSize . y , ( int ) ( round ( m - > refreshRate * 1000 ) ) ) ;
2022-03-21 15:17:04 +01:00
}
wlr_output_manager_v1_set_configuration ( g_pCompositor - > m_sWLROutputMgr , CONFIG ) ;
}
2022-06-17 20:31:15 +02:00
void Events : : listener_newOutput ( wl_listener * listener , void * data ) {
2022-03-21 15:17:04 +01:00
// new monitor added, let's accomodate for that.
2022-06-17 20:31:15 +02:00
const auto OUTPUT = ( wlr_output * ) data ;
2022-03-21 15:17:04 +01:00
2022-06-17 20:31:15 +02:00
if ( ! OUTPUT - > name ) {
2022-05-29 20:15:34 +02:00
Debug : : log ( ERR , " New monitor has no name?? Ignoring " ) ;
return ;
}
2022-08-10 21:54:09 +02:00
if ( g_pCompositor - > m_bUnsafeState ) {
Debug : : log ( WARN , " Recovering from an unsafe state. May you be lucky. " ) ;
2022-05-29 20:15:34 +02:00
}
2022-07-27 12:32:00 +02:00
// add it to real
2022-08-10 21:54:09 +02:00
std : : shared_ptr < CMonitor > * PNEWMONITORWRAP = nullptr ;
for ( auto & rm : g_pCompositor - > m_vRealMonitors ) {
if ( rm - > szName = = OUTPUT - > name ) {
PNEWMONITORWRAP = & rm ;
Debug : : log ( LOG , " Recovering a removed monitor. " ) ;
break ;
}
}
if ( ! PNEWMONITORWRAP ) {
Debug : : log ( LOG , " Adding completely new monitor. " ) ;
PNEWMONITORWRAP = & g_pCompositor - > m_vRealMonitors . emplace_back ( std : : make_shared < CMonitor > ( ) ) ;
2022-03-21 15:17:04 +01:00
2022-08-10 21:54:09 +02:00
( * PNEWMONITORWRAP ) - > ID = g_pCompositor - > getNextAvailableMonitorID ( ) ;
}
const auto PNEWMONITOR = PNEWMONITORWRAP - > get ( ) ;
2022-08-03 16:19:00 +02:00
2022-07-27 12:32:00 +02:00
PNEWMONITOR - > output = OUTPUT ;
PNEWMONITOR - > m_pThisWrap = PNEWMONITORWRAP ;
2022-06-21 22:13:13 +02:00
2022-07-27 12:32:00 +02:00
PNEWMONITOR - > onConnect ( false ) ;
2022-04-20 19:36:05 +02:00
2022-08-10 13:44:04 +02:00
if ( ( ! pMostHzMonitor | | PNEWMONITOR - > refreshRate > pMostHzMonitor - > refreshRate ) & & PNEWMONITOR - > m_bEnabled )
2022-07-12 10:02:12 +02:00
pMostHzMonitor = PNEWMONITOR ;
2022-04-28 17:57:24 +02:00
// ready to process cuz we have a monitor
2022-08-10 21:54:09 +02:00
if ( PNEWMONITOR - > m_bEnabled ) {
2022-08-10 13:44:04 +02:00
g_pCompositor - > m_bReadyToProcess = true ;
2022-08-10 21:54:09 +02:00
g_pCompositor - > m_bUnsafeState = false ;
}
2022-03-21 15:17:04 +01:00
}
2022-06-17 20:31:15 +02:00
void Events : : listener_monitorFrame ( void * owner , void * data ) {
2022-07-27 12:32:00 +02:00
CMonitor * const PMONITOR = ( CMonitor * ) owner ;
2022-03-21 15:17:04 +01:00
2022-08-10 21:54:09 +02:00
if ( ( g_pCompositor - > m_sWLRSession & & ! g_pCompositor - > m_sWLRSession - > active ) | | ! g_pCompositor - > m_bSessionActive | | g_pCompositor - > m_bUnsafeState ) {
2022-07-13 18:18:23 +02:00
Debug : : log ( WARN , " Attempted to render frame on inactive session! " ) ;
return ; // cannot draw on session inactive (different tty)
}
2022-07-27 12:32:00 +02:00
if ( ! PMONITOR - > m_bEnabled )
return ;
2022-07-13 18:18:23 +02:00
2022-05-28 17:32:19 +02:00
static std : : chrono : : high_resolution_clock : : time_point startRender = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-05-28 17:40:57 +02:00
static std : : chrono : : high_resolution_clock : : time_point startRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
static std : : chrono : : high_resolution_clock : : time_point endRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-05-28 17:32:19 +02:00
2022-06-07 20:41:40 +02:00
static auto * const PDEBUGOVERLAY = & g_pConfigManager - > getConfigValuePtr ( " debug:overlay " ) - > intValue ;
static auto * const PDAMAGETRACKINGMODE = & g_pConfigManager - > getConfigValuePtr ( " general:damage_tracking_internal " ) - > intValue ;
2022-06-29 11:44:00 +02:00
static auto * const PDAMAGEBLINK = & g_pConfigManager - > getConfigValuePtr ( " debug:damage_blink " ) - > intValue ;
2022-07-12 10:02:12 +02:00
static auto * const PNOVFR = & g_pConfigManager - > getConfigValuePtr ( " misc:no_vfr " ) - > intValue ;
2022-06-29 11:44:00 +02:00
static int damageBlinkCleanup = 0 ; // because double-buffered
2022-06-07 20:41:40 +02:00
2022-07-31 16:54:36 +02:00
if ( ! * PDAMAGEBLINK )
damageBlinkCleanup = 0 ;
2022-06-17 20:31:15 +02:00
if ( * PDEBUGOVERLAY = = 1 ) {
2022-05-28 17:32:19 +02:00
startRender = std : : chrono : : high_resolution_clock : : now ( ) ;
g_pDebugOverlay - > frameData ( PMONITOR ) ;
}
2022-07-13 18:18:23 +02:00
if ( PMONITOR - > framesToSkip > 0 ) {
PMONITOR - > framesToSkip - = 1 ;
if ( ! PMONITOR - > noFrameSchedule )
g_pCompositor - > scheduleFrameForMonitor ( PMONITOR ) ;
else {
Debug : : log ( LOG , " NoFrameSchedule hit for %s. " , PMONITOR - > szName . c_str ( ) ) ;
}
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( PMONITOR - > ID ) ;
2022-07-31 16:54:36 +02:00
if ( PMONITOR - > framesToSkip > 10 )
PMONITOR - > framesToSkip = 0 ;
2022-07-13 18:18:23 +02:00
return ;
}
2022-07-11 23:56:24 +02:00
// checks //
2022-07-12 10:02:12 +02:00
if ( PMONITOR - > ID = = pMostHzMonitor - > ID | | ! * PNOVFR ) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
g_pCompositor - > sanityCheckWorkspaces ( ) ;
g_pAnimationManager - > tick ( ) ;
2022-04-12 20:02:57 +02:00
2022-07-12 10:02:12 +02:00
g_pConfigManager - > dispatchExecOnce ( ) ; // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
2022-04-19 19:01:23 +02:00
2022-07-12 10:02:12 +02:00
if ( g_pConfigManager - > m_bWantsMonitorReload )
g_pConfigManager - > performMonitorReload ( ) ;
2022-06-24 23:27:02 +02:00
2022-07-12 10:02:12 +02:00
g_pHyprRenderer - > ensureCursorRenderingMode ( ) ; // so that the cursor gets hidden/shown if the user requested timeouts
}
2022-07-11 23:56:24 +02:00
// //
2022-03-23 22:01:59 +01:00
2022-07-26 18:22:34 +02:00
if ( PMONITOR - > scheduledRecalc ) {
PMONITOR - > scheduledRecalc = false ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( PMONITOR - > ID ) ;
}
2022-03-21 15:17:04 +01:00
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
2022-04-14 16:43:29 +02:00
// check the damage
pixman_region32_t damage ;
bool hasChanged ;
pixman_region32_init ( & damage ) ;
2022-06-17 20:31:15 +02:00
if ( * PDAMAGETRACKINGMODE = = - 1 ) {
2022-04-14 16:43:29 +02:00
Debug : : log ( CRIT , " Damage tracking mode -1 ???? " ) ;
2022-03-21 15:17:04 +01:00
return ;
2022-04-14 16:43:29 +02:00
}
2022-03-21 15:17:04 +01:00
2022-08-01 20:18:26 +02:00
g_pHyprOpenGL - > preRender ( PMONITOR ) ;
2022-06-17 20:31:15 +02:00
if ( ! wlr_output_damage_attach_render ( PMONITOR - > damage , & hasChanged , & damage ) ) {
2022-04-14 16:43:29 +02:00
Debug : : log ( ERR , " Couldn't attach render to display %s ??? " , PMONITOR - > szName . c_str ( ) ) ;
return ;
}
2022-07-12 23:11:34 +02:00
// we need to cleanup fading out when rendering the appropriate context
g_pCompositor - > cleanupFadingOut ( PMONITOR - > ID ) ;
2022-06-29 11:44:00 +02:00
if ( ! hasChanged & & * PDAMAGETRACKINGMODE ! = DAMAGE_TRACKING_NONE & & PMONITOR - > forceFullFrames = = 0 & & damageBlinkCleanup = = 0 ) {
2022-04-14 16:43:29 +02:00
pixman_region32_fini ( & damage ) ;
wlr_output_rollback ( PMONITOR - > output ) ;
2022-07-04 17:47:31 +02:00
2022-07-12 10:02:12 +02:00
if ( * PDAMAGEBLINK | | * PNOVFR )
2022-07-13 18:18:23 +02:00
g_pCompositor - > scheduleFrameForMonitor ( PMONITOR ) ;
2022-07-04 17:47:31 +02:00
2022-04-14 16:43:29 +02:00
return ;
}
// if we have no tracking or full tracking, invalidate the entire monitor
2022-06-29 11:44:00 +02:00
if ( * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_NONE | | * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_MONITOR | | PMONITOR - > forceFullFrames > 0 | | damageBlinkCleanup > 0 ) {
2022-05-29 12:27:45 +02:00
pixman_region32_union_rect ( & damage , & damage , 0 , 0 , ( int ) PMONITOR - > vecTransformedSize . x , ( int ) PMONITOR - > vecTransformedSize . y ) ;
2022-05-06 16:06:21 +02:00
pixman_region32_copy ( & g_pHyprOpenGL - > m_rOriginalDamageRegion , & damage ) ;
2022-06-17 20:31:15 +02:00
} else {
static auto * const PBLURENABLED = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur " ) - > intValue ;
2022-05-18 20:33:54 +02:00
2022-05-06 16:06:21 +02:00
// if we use blur we need to expand the damage for proper blurring
2022-06-17 20:31:15 +02:00
if ( * PBLURENABLED = = 1 ) {
2022-05-06 16:06:21 +02:00
// TODO: can this be optimized?
2022-06-17 20:31:15 +02:00
static auto * const PBLURSIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_size " ) - > intValue ;
static auto * const PBLURPASSES = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_passes " ) - > intValue ;
const auto BLURRADIUS = * PBLURSIZE * pow ( 2 , * PBLURPASSES ) ; // is this 2^pass? I don't know but it works... I think.
2022-05-06 16:06:21 +02:00
pixman_region32_copy ( & g_pHyprOpenGL - > m_rOriginalDamageRegion , & damage ) ;
// now, prep the damage, get the extended damage region
2022-06-17 20:31:15 +02:00
wlr_region_expand ( & damage , & damage , BLURRADIUS ) ; // expand for proper blurring
} else {
2022-05-25 19:19:54 +02:00
pixman_region32_copy ( & g_pHyprOpenGL - > m_rOriginalDamageRegion , & damage ) ;
2022-05-06 16:06:21 +02:00
}
2022-04-14 16:43:29 +02:00
}
2022-07-31 16:54:36 +02:00
if ( PMONITOR - > forceFullFrames > 0 ) {
2022-06-21 22:13:13 +02:00
PMONITOR - > forceFullFrames - = 1 ;
2022-07-31 16:54:36 +02:00
if ( PMONITOR - > forceFullFrames > 10 )
PMONITOR - > forceFullFrames = 0 ;
}
2022-06-21 22:13:13 +02:00
2022-04-14 16:43:29 +02:00
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
g_pHyprOpenGL - > begin ( PMONITOR , & damage ) ;
2022-07-10 11:45:50 +02:00
g_pHyprOpenGL - > clear ( CColor ( 17 , 17 , 17 , 255 ) ) ;
2022-04-10 14:32:18 +02:00
g_pHyprOpenGL - > clearWithTex ( ) ; // will apply the hypr "wallpaper"
2022-03-21 15:17:04 +01:00
2022-04-05 14:33:54 +02:00
g_pHyprRenderer - > renderAllClientsForMonitor ( PMONITOR - > ID , & now ) ;
2022-03-21 15:17:04 +01:00
2022-05-28 17:32:19 +02:00
// if correct monitor draw hyprerror
if ( PMONITOR - > ID = = 0 )
g_pHyprError - > draw ( ) ;
// for drawing the debug overlay
2022-06-17 20:31:15 +02:00
if ( PMONITOR - > ID = = 0 & & * PDEBUGOVERLAY = = 1 ) {
2022-05-28 17:40:57 +02:00
startRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-05-28 17:32:19 +02:00
g_pDebugOverlay - > draw ( ) ;
2022-05-28 17:40:57 +02:00
endRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
}
2022-05-28 17:32:19 +02:00
2022-06-29 11:44:00 +02:00
if ( * PDAMAGEBLINK & & damageBlinkCleanup = = 0 ) {
wlr_box monrect = { 0 , 0 , PMONITOR - > vecPixelSize . x , PMONITOR - > vecPixelSize . y } ;
g_pHyprOpenGL - > renderRect ( & monrect , CColor ( 255 , 0 , 255 , 100 ) , 0 ) ;
damageBlinkCleanup = 1 ;
} else if ( * PDAMAGEBLINK ) {
damageBlinkCleanup + + ;
if ( damageBlinkCleanup > 3 )
damageBlinkCleanup = 0 ;
}
2022-05-18 20:33:54 +02:00
wlr_renderer_begin ( g_pCompositor - > m_sWLRRenderer , PMONITOR - > vecPixelSize . x , PMONITOR - > vecPixelSize . y ) ;
2022-05-16 21:30:11 +02:00
2022-04-05 14:33:54 +02:00
wlr_output_render_software_cursors ( PMONITOR - > output , NULL ) ;
2022-04-04 19:44:25 +02:00
2022-04-05 14:33:54 +02:00
wlr_renderer_end ( g_pCompositor - > m_sWLRRenderer ) ;
2022-04-04 19:44:25 +02:00
2022-04-05 14:33:54 +02:00
g_pHyprOpenGL - > end ( ) ;
2022-03-21 15:17:04 +01:00
2022-04-14 16:43:29 +02:00
// calc frame damage
pixman_region32_t frameDamage ;
pixman_region32_init ( & frameDamage ) ;
const auto TRANSFORM = wlr_output_transform_invert ( PMONITOR - > output - > transform ) ;
2022-05-29 12:27:45 +02:00
wlr_region_transform ( & frameDamage , & PMONITOR - > damage - > current , TRANSFORM , ( int ) PMONITOR - > vecTransformedSize . x , ( int ) PMONITOR - > vecTransformedSize . y ) ;
2022-05-18 20:33:54 +02:00
2022-06-07 20:41:40 +02:00
if ( * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_NONE | | * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_MONITOR )
2022-05-29 12:27:45 +02:00
pixman_region32_union_rect ( & frameDamage , & frameDamage , 0 , 0 , ( int ) PMONITOR - > vecTransformedSize . x , ( int ) PMONITOR - > vecTransformedSize . y ) ;
2022-04-14 16:43:29 +02:00
2022-06-29 11:44:00 +02:00
if ( * PDAMAGEBLINK )
pixman_region32_union ( & frameDamage , & frameDamage , & damage ) ;
2022-04-14 16:43:29 +02:00
wlr_output_set_damage ( PMONITOR - > output , & frameDamage ) ;
pixman_region32_fini ( & frameDamage ) ;
pixman_region32_fini ( & damage ) ;
2022-03-21 15:17:04 +01:00
wlr_output_commit ( PMONITOR - > output ) ;
2022-04-14 16:43:29 +02:00
2022-07-12 10:02:12 +02:00
if ( * PDAMAGEBLINK | | * PNOVFR )
2022-07-13 18:18:23 +02:00
g_pCompositor - > scheduleFrameForMonitor ( PMONITOR ) ;
2022-05-28 17:32:19 +02:00
2022-06-17 20:31:15 +02:00
if ( * PDEBUGOVERLAY = = 1 ) {
2022-05-28 17:40:57 +02:00
const float µ s = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - startRender ) . count ( ) / 1000.f ;
g_pDebugOverlay - > renderData ( PMONITOR , µ s ) ;
2022-06-17 20:31:15 +02:00
if ( PMONITOR - > ID = = 0 ) {
2022-05-28 17:40:57 +02:00
const float µ sNoOverlay = µ s - std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( endRenderOverlay - startRenderOverlay ) . count ( ) / 1000.f ;
g_pDebugOverlay - > renderDataNoOverlay ( PMONITOR , µ sNoOverlay ) ;
2022-06-17 20:31:15 +02:00
} else {
2022-05-28 17:40:57 +02:00
g_pDebugOverlay - > renderDataNoOverlay ( PMONITOR , µ s ) ;
}
}
2022-03-21 15:17:04 +01:00
}
2022-06-17 20:31:15 +02:00
void Events : : listener_monitorDestroy ( void * owner , void * data ) {
const auto OUTPUT = ( wlr_output * ) data ;
2022-03-21 15:17:04 +01:00
2022-07-27 12:32:00 +02:00
CMonitor * pMonitor = nullptr ;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( m - > szName = = OUTPUT - > name ) {
pMonitor = m . get ( ) ;
2022-03-21 15:17:04 +01:00
break ;
}
}
if ( ! pMonitor )
return ;
2022-07-27 12:32:00 +02:00
pMonitor - > onDisconnect ( ) ;
2022-05-31 17:17:44 +02:00
2022-08-10 21:54:09 +02:00
// cleanup if not unsafe
2022-07-12 10:02:12 +02:00
2022-08-10 21:54:09 +02:00
if ( ! g_pCompositor - > m_bUnsafeState ) {
g_pCompositor - > m_vRealMonitors . erase ( std : : remove_if ( g_pCompositor - > m_vRealMonitors . begin ( ) , g_pCompositor - > m_vRealMonitors . end ( ) , [ & ] ( std : : shared_ptr < CMonitor > & el ) { return el . get ( ) = = pMonitor ; } ) ) ;
2022-07-12 10:02:12 +02:00
2022-08-10 21:54:09 +02:00
if ( pMostHzMonitor = = pMonitor ) {
int mostHz = 0 ;
CMonitor * pMonitorMostHz = nullptr ;
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( m - > refreshRate > mostHz ) {
pMonitorMostHz = m . get ( ) ;
mostHz = m - > refreshRate ;
}
2022-07-12 10:02:12 +02:00
}
2022-08-10 21:54:09 +02:00
pMostHzMonitor = pMonitorMostHz ;
}
2022-07-12 10:02:12 +02:00
}
2022-03-21 15:17:04 +01:00
}