2022-03-17 20:22:29 +01:00
# include "Renderer.hpp"
# include "../Compositor.hpp"
void renderSurface ( struct wlr_surface * surface , int x , int y , void * data ) {
const auto TEXTURE = wlr_surface_get_texture ( surface ) ;
const auto RDATA = ( SRenderData * ) data ;
if ( ! TEXTURE )
return ;
double outputX = 0 , outputY = 0 ;
wlr_output_layout_output_coords ( g_pCompositor - > m_sWLROutputLayout , RDATA - > output , & outputX , & outputY ) ;
2022-03-23 22:01:59 +01:00
wlr_box windowBox ;
2022-07-04 15:58:12 +02:00
if ( RDATA - > surface & & surface = = RDATA - > surface )
2022-06-29 12:54:53 +02:00
windowBox = { ( int ) outputX + RDATA - > x + x , ( int ) outputY + RDATA - > y + y , RDATA - > w , RDATA - > h } ;
2022-07-04 15:58:12 +02:00
else // here we clamp to 2, these might be some tiny specks
2022-06-29 12:54:53 +02:00
windowBox = { ( int ) outputX + RDATA - > x + x , ( int ) outputY + RDATA - > y + y , std : : clamp ( surface - > current . width , 2 , 1337420 ) , std : : clamp ( surface - > current . height , 2 , 1337420 ) } ;
2022-07-11 23:38:10 +02:00
2022-07-15 19:07:06 +02:00
// squish all oversized but dont in some cases, jesus christ this is a mess
// TODO: this shouldn't be done this way. Custom UV here as well.
// this is fucking horrible
// Issue: will cause oversized apps with reserved area to overflow from the window box. (see chromium on ozone wayland)
const auto PRESQUISHSIZE = Vector2D ( windowBox . width , windowBox . height ) ;
2022-07-11 23:38:10 +02:00
if ( RDATA - > squishOversized ) {
if ( x + windowBox . width > RDATA - > w )
windowBox . width = RDATA - > w - x ;
2022-07-15 19:07:06 +02:00
if ( y + windowBox . height > RDATA - > h )
2022-07-11 23:38:10 +02:00
windowBox . height = RDATA - > h - y ;
}
2022-03-17 20:22:29 +01:00
scaleBox ( & windowBox , RDATA - > output - > scale ) ;
2022-06-07 20:41:40 +02:00
static auto * const PROUNDING = & g_pConfigManager - > getConfigValuePtr ( " decoration:rounding " ) - > intValue ;
float rounding = RDATA - > dontRound ? 0 : RDATA - > rounding = = - 1 ? * PROUNDING : RDATA - > rounding ;
2022-08-10 18:10:38 +02:00
rounding / = RDATA - > output - > scale ;
2022-05-28 17:48:01 +02:00
2022-06-22 15:45:56 +02:00
if ( RDATA - > surface & & surface = = RDATA - > surface ) {
2022-07-28 18:17:47 +02:00
if ( wlr_surface_is_xwayland_surface ( surface ) & & ! wlr_xwayland_surface_from_wlr_surface ( surface ) - > has_alpha & & RDATA - > fadeAlpha * RDATA - > alpha = = 255.f ) {
2022-07-06 22:12:03 +02:00
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , true ) ;
2022-07-27 13:30:55 +02:00
} else {
if ( RDATA - > blur )
g_pHyprOpenGL - > renderTextureWithBlur ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , surface , rounding ) ;
else
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , true ) ;
}
2022-06-22 15:45:56 +02:00
}
2022-07-04 15:58:12 +02:00
else {
2022-07-04 17:48:04 +02:00
if ( RDATA - > surface & & wlr_surface_is_xdg_surface ( RDATA - > surface ) ) {
2022-07-04 15:58:12 +02:00
wlr_box geo ;
wlr_xdg_surface_get_geometry ( wlr_xdg_surface_from_wlr_surface ( RDATA - > surface ) , & geo ) ;
2022-07-15 19:07:06 +02:00
// TODO: continuation of the above madness.
if ( geo . x ! = 0 | | geo . y ! = 0 ) {
windowBox . width = PRESQUISHSIZE . x ;
windowBox . height = PRESQUISHSIZE . y ;
}
2022-07-04 15:58:12 +02:00
windowBox . x - = geo . x ;
windowBox . y - = geo . y ;
}
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , false ) ;
}
2022-03-17 20:22:29 +01:00
wlr_surface_send_frame_done ( surface , RDATA - > when ) ;
wlr_presentation_surface_sampled_on_output ( g_pCompositor - > m_sWLRPresentation , surface , RDATA - > output ) ;
}
2022-07-27 12:32:00 +02:00
bool CHyprRenderer : : shouldRenderWindow ( CWindow * pWindow , CMonitor * pMonitor ) {
2022-05-30 14:55:42 +02:00
wlr_box geometry = pWindow - > getFullWindowBoundingBox ( ) ;
2022-03-20 18:49:40 +01:00
if ( ! wlr_output_layout_intersects ( g_pCompositor - > m_sWLROutputLayout , pMonitor - > output , & geometry ) )
return false ;
// now check if it has the same workspace
2022-07-28 16:33:45 +02:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
2022-07-28 17:56:11 +02:00
if ( PWORKSPACE & & PWORKSPACE - > m_iMonitorID = = pMonitor - > ID ) {
2022-07-28 16:33:45 +02:00
if ( ! ( ! PWORKSPACE - > m_bHasFullscreenWindow | | pWindow - > m_bIsFullscreen | | ( pWindow - > m_bIsFloating & & pWindow - > m_bCreatedOverFullscreen ) ) )
return false ;
}
2022-03-20 18:49:40 +01:00
if ( pWindow - > m_iWorkspaceID = = pMonitor - > activeWorkspace )
return true ;
2022-07-07 11:52:12 +02:00
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
if ( g_pCompositor - > isWorkspaceVisible ( pWindow - > m_iWorkspaceID ) | | ( PWORKSPACE & & PWORKSPACE - > m_iMonitorID = = pMonitor - > ID & & PWORKSPACE - > m_bForceRendering ) | | ( PWORKSPACE & & PWORKSPACE - > m_iMonitorID = = pMonitor - > ID & & ( PWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWORKSPACE - > m_fAlpha . isBeingAnimated ( ) ) ) )
2022-03-22 20:04:39 +01:00
return true ;
2022-03-20 18:49:40 +01:00
2022-05-31 14:01:00 +02:00
if ( pMonitor - > specialWorkspaceOpen & & pWindow - > m_iWorkspaceID = = SPECIAL_WORKSPACE_ID )
return true ;
2022-03-20 18:49:40 +01:00
return false ;
}
2022-05-31 22:16:13 +02:00
bool CHyprRenderer : : shouldRenderWindow ( CWindow * pWindow ) {
if ( ! g_pCompositor - > windowValidMapped ( pWindow ) )
return false ;
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( g_pCompositor - > isWorkspaceVisible ( pWindow - > m_iWorkspaceID ) )
return true ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( PWORKSPACE & & PWORKSPACE - > m_iMonitorID = = m - > ID & & ( PWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWORKSPACE - > m_fAlpha . isBeingAnimated ( ) ) )
2022-05-31 22:16:13 +02:00
return true ;
2022-06-30 15:44:26 +02:00
if ( m - > specialWorkspaceOpen & & pWindow - > m_iWorkspaceID = = SPECIAL_WORKSPACE_ID )
2022-05-31 22:16:13 +02:00
return true ;
}
return false ;
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderWorkspaceWithFullscreenWindow ( CMonitor * pMonitor , CWorkspace * pWorkspace , timespec * time ) {
2022-03-30 20:16:23 +02:00
CWindow * pWorkspaceWindow = nullptr ;
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
2022-07-28 15:56:55 +02:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ;
if ( w - > m_iWorkspaceID ! = pWorkspace - > m_iID | | ! w - > m_bIsFullscreen ) {
if ( ! ( PWORKSPACE & & ( PWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWORKSPACE - > m_fAlpha . isBeingAnimated ( ) ) ) )
continue ;
}
2022-03-21 19:18:33 +01:00
2022-07-28 16:33:45 +02:00
if ( w - > m_iWorkspaceID = = pMonitor - > activeWorkspace & & ! w - > m_bIsFullscreen )
continue ;
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , pMonitor , time , pWorkspace - > m_efFullscreenMode ! = FULLSCREEN_FULL , RENDER_PASS_ALL ) ;
2022-03-30 20:16:23 +02:00
2022-06-30 15:44:26 +02:00
pWorkspaceWindow = w . get ( ) ;
2022-03-30 20:16:23 +02:00
}
// then render windows over fullscreen
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_iWorkspaceID ! = pWorkspaceWindow - > m_iWorkspaceID | | ! w - > m_bCreatedOverFullscreen | | ! w - > m_bIsMapped )
2022-03-30 20:16:23 +02:00
continue ;
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2022-05-31 14:20:41 +02:00
}
// and then special windows
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( ! g_pCompositor - > windowValidMapped ( w . get ( ) ) & & ! w - > m_bFadingOut )
2022-05-31 14:20:41 +02:00
continue ;
2022-06-30 15:44:26 +02:00
if ( w - > m_iWorkspaceID ! = SPECIAL_WORKSPACE_ID )
2022-05-31 14:20:41 +02:00
continue ;
2022-06-30 15:44:26 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor ) )
2022-05-31 14:20:41 +02:00
continue ;
// render the bad boy
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2022-03-21 19:18:33 +01:00
}
2022-03-31 17:25:23 +02:00
2022-04-25 21:49:45 +02:00
// and the overlay layers
2022-05-29 15:44:30 +02:00
if ( pWorkspace - > m_efFullscreenMode ! = FULLSCREEN_FULL ) {
// on non-full we draw the bar and shit
for ( auto & ls : pMonitor - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_TOP ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , pMonitor , time ) ;
2022-05-29 15:44:30 +02:00
}
}
2022-04-25 21:49:45 +02:00
for ( auto & ls : pMonitor - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , pMonitor , time ) ;
2022-04-25 21:49:45 +02:00
}
2022-03-31 17:25:23 +02:00
renderDragIcon ( pMonitor , time ) ;
2022-04-08 21:40:41 +02:00
// if correct monitor draw hyprerror
2022-06-30 15:44:26 +02:00
if ( pMonitor = = g_pCompositor - > m_vMonitors . front ( ) . get ( ) )
2022-04-08 21:40:41 +02:00
g_pHyprError - > draw ( ) ;
2022-03-21 19:18:33 +01:00
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderWindow ( CWindow * pWindow , CMonitor * pMonitor , timespec * time , bool decorate , eRenderPassMode mode ) {
2022-04-12 16:44:18 +02:00
if ( pWindow - > m_bHidden )
return ;
2022-04-05 20:49:15 +02:00
if ( pWindow - > m_bFadingOut ) {
2022-05-28 18:52:22 +02:00
if ( pMonitor - > ID = = pWindow - > m_iMonitorID ) // TODO: fix this
g_pHyprOpenGL - > renderSnapshot ( & pWindow ) ;
2022-04-05 20:49:15 +02:00
return ;
}
2022-05-12 11:27:31 +02:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
const auto REALPOS = pWindow - > m_vRealPosition . vec ( ) + PWORKSPACE - > m_vRenderOffset . vec ( ) ;
2022-06-21 22:54:41 +02:00
static const auto PNOFLOATINGBORDERS = & g_pConfigManager - > getConfigValuePtr ( " general:no_border_on_floating " ) - > intValue ;
2022-03-23 22:01:59 +01:00
SRenderData renderdata = { pMonitor - > output , time , REALPOS . x , REALPOS . y } ;
renderdata . surface = g_pXWaylandManager - > getWindowSurface ( pWindow ) ;
2022-05-22 11:42:18 +02:00
renderdata . w = std : : clamp ( pWindow - > m_vRealSize . vec ( ) . x , ( double ) 5 , ( double ) 1337420 ) ; // clamp the size to min 5,
renderdata . h = std : : clamp ( pWindow - > m_vRealSize . vec ( ) . y , ( double ) 5 , ( double ) 1337420 ) ; // otherwise we'll have issues later with invalid boxes
2022-08-01 12:57:37 +02:00
renderdata . dontRound = ( pWindow - > m_bIsFullscreen & & PWORKSPACE - > m_efFullscreenMode = = FULLSCREEN_FULL ) | | ( ! pWindow - > m_sSpecialRenderData . rounding ) ;
2022-05-16 23:13:32 +02:00
renderdata . fadeAlpha = pWindow - > m_fAlpha . fl ( ) * ( PWORKSPACE - > m_fAlpha . fl ( ) / 255.f ) ;
2022-07-12 13:40:55 +02:00
renderdata . alpha = pWindow - > m_fActiveInactiveAlpha . fl ( ) ;
2022-06-26 22:27:03 +02:00
renderdata . decorate = decorate & & ! pWindow - > m_bX11DoesntWantBorders & & ( pWindow - > m_bIsFloating ? * PNOFLOATINGBORDERS = = 0 : true ) & & ( ! pWindow - > m_bIsFullscreen | | PWORKSPACE - > m_efFullscreenMode ! = FULLSCREEN_FULL ) ;
2022-08-01 12:57:37 +02:00
renderdata . rounding = pWindow - > m_sAdditionalConfigData . rounding ;
2022-07-06 22:12:03 +02:00
renderdata . blur = true ; // if it shouldn't, it will be ignored later
2022-03-21 19:18:33 +01:00
2022-04-22 14:37:38 +02:00
// apply window special data
2022-05-31 17:35:50 +02:00
if ( pWindow - > m_sSpecialRenderData . alphaInactive = = - 1 )
renderdata . alpha * = pWindow - > m_sSpecialRenderData . alpha ;
else
renderdata . alpha * = pWindow = = g_pCompositor - > m_pLastWindow ? pWindow - > m_sSpecialRenderData . alpha : pWindow - > m_sSpecialRenderData . alphaInactive ;
2022-04-22 14:37:38 +02:00
2022-07-28 12:07:41 +02:00
// apply opaque
if ( pWindow - > m_sAdditionalConfigData . forceOpaque )
renderdata . alpha = 1.f ;
2022-05-17 13:16:37 +02:00
g_pHyprOpenGL - > m_pCurrentWindow = pWindow ;
2022-03-21 19:18:33 +01:00
2022-06-28 15:45:38 +02:00
// render window decorations first, if not fullscreen full
2022-05-28 20:46:20 +02:00
2022-07-12 09:49:56 +02:00
if ( mode = = RENDER_PASS_ALL | | mode = = RENDER_PASS_MAIN ) {
if ( ! pWindow - > m_bIsFullscreen | | PWORKSPACE - > m_efFullscreenMode ! = FULLSCREEN_FULL ) for ( auto & wd : pWindow - > m_dWindowDecorations )
wd - > draw ( pMonitor , renderdata . alpha * renderdata . fadeAlpha / 255.f ) ;
2022-06-22 15:45:56 +02:00
2022-07-12 09:49:56 +02:00
if ( ! pWindow - > m_bIsX11 ) {
wlr_box geom ;
wlr_xdg_surface_get_geometry ( pWindow - > m_uSurface . xdg , & geom ) ;
2022-07-15 19:07:06 +02:00
// first, check for poorly sized windows.
2022-07-12 09:49:56 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( ( double ) geom . x / ( double ) pWindow - > m_uSurface . xdg - > surface - > current . width , ( double ) geom . y / ( double ) pWindow - > m_uSurface . xdg - > surface - > current . height ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( ( double ) ( geom . width + geom . x ) / ( double ) pWindow - > m_uSurface . xdg - > surface - > current . width , ( double ) ( geom . y + geom . height ) / ( double ) pWindow - > m_uSurface . xdg - > surface - > current . height ) ;
if ( g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = = Vector2D ( ) & & g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = = Vector2D ( 1 , 1 ) ) {
// No special UV mods needed
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
}
2022-07-15 19:07:06 +02:00
// then, if the surface is too big, modify the pos UV
if ( geom . width > renderdata . w + 1 | | geom . height > renderdata . h + 1 ) {
const auto OFF = Vector2D ( renderdata . w / ( double ) geom . width , renderdata . h / ( double ) geom . height ) ;
if ( g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = = Vector2D ( - 1 , - 1 ) )
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( 0 , 0 ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D (
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight . x * ( ( double ) renderdata . w / ( ( double ) geom . width / g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight . x ) ) ,
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight . y * ( ( double ) renderdata . h / ( ( double ) geom . height / g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight . y ) )
) ;
}
2022-07-12 09:49:56 +02:00
} else {
2022-06-22 15:45:56 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
}
2022-07-12 09:49:56 +02:00
wlr_surface_for_each_surface ( g_pXWaylandManager - > getWindowSurface ( pWindow ) , renderSurface , & renderdata ) ;
2022-07-16 20:57:59 +02:00
if ( renderdata . decorate ) {
static auto * const PROUNDING = & g_pConfigManager - > getConfigValuePtr ( " decoration:rounding " ) - > intValue ;
float rounding = renderdata . dontRound ? 0 : renderdata . rounding = = - 1 ? * PROUNDING : renderdata . rounding ;
2022-08-10 18:10:38 +02:00
rounding / = pMonitor - > scale ;
2022-07-16 20:57:59 +02:00
auto col = g_pHyprOpenGL - > m_pCurrentWindow - > m_cRealBorderColor . col ( ) ;
col . a * = renderdata . fadeAlpha * renderdata . alpha / 255.f ;
wlr_box windowBox = { renderdata . x - pMonitor - > vecPosition . x , renderdata . y - pMonitor - > vecPosition . y , renderdata . w , renderdata . h } ;
2022-07-16 23:29:42 +02:00
scaleBox ( & windowBox , pMonitor - > scale ) ;
2022-07-16 20:57:59 +02:00
g_pHyprOpenGL - > renderBorder ( & windowBox , col , rounding ) ;
}
2022-07-04 15:58:12 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
2022-06-22 15:45:56 +02:00
}
2022-07-12 09:49:56 +02:00
if ( mode = = RENDER_PASS_ALL | | mode = = RENDER_PASS_POPUP ) {
if ( ! pWindow - > m_bIsX11 ) {
renderdata . dontRound = false ; // restore dontround
renderdata . pMonitor = pMonitor ;
2022-07-15 19:07:06 +02:00
renderdata . squishOversized = false ; // don't squish popups
2022-07-12 09:49:56 +02:00
wlr_xdg_surface_for_each_popup_surface ( pWindow - > m_uSurface . xdg , renderSurface , & renderdata ) ;
}
2022-05-17 13:16:37 +02:00
}
g_pHyprOpenGL - > m_pCurrentWindow = nullptr ;
2022-03-21 19:18:33 +01:00
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderLayer ( SLayerSurface * pLayer , CMonitor * pMonitor , timespec * time ) {
2022-05-14 17:23:46 +02:00
if ( pLayer - > fadingOut ) {
g_pHyprOpenGL - > renderSnapshot ( & pLayer ) ;
return ;
}
SRenderData renderdata = { pMonitor - > output , time , pLayer - > geometry . x , pLayer - > geometry . y } ;
renderdata . fadeAlpha = pLayer - > alpha . fl ( ) ;
2022-07-06 22:12:03 +02:00
renderdata . blur = pLayer - > forceBlur ;
renderdata . surface = pLayer - > layerSurface - > surface ;
renderdata . decorate = false ;
2022-07-07 12:40:32 +02:00
renderdata . w = pLayer - > layerSurface - > surface - > current . width ;
renderdata . h = pLayer - > layerSurface - > surface - > current . height ;
2022-05-14 17:23:46 +02:00
wlr_surface_for_each_surface ( pLayer - > layerSurface - > surface , renderSurface , & renderdata ) ;
2022-07-27 18:02:20 +02:00
renderdata . squishOversized = false ; // don't squish popups
wlr_layer_surface_v1_for_each_popup_surface ( pLayer - > layerSurface , renderSurface , & renderdata ) ;
2022-05-14 17:23:46 +02:00
}
2022-08-05 17:07:01 +02:00
void CHyprRenderer : : renderIMEPopup ( SIMEPopup * pPopup , CMonitor * pMonitor , timespec * time ) {
SRenderData renderdata = { pMonitor - > output , time , pPopup - > realX , pPopup - > realY } ;
renderdata . blur = false ;
renderdata . surface = pPopup - > pSurface - > surface ;
renderdata . decorate = false ;
renderdata . w = pPopup - > pSurface - > surface - > current . width ;
renderdata . h = pPopup - > pSurface - > surface - > current . height ;
wlr_surface_for_each_surface ( pPopup - > pSurface - > surface , renderSurface , & renderdata ) ;
}
2022-03-17 20:22:29 +01:00
void CHyprRenderer : : renderAllClientsForMonitor ( const int & ID , timespec * time ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( ID ) ;
if ( ! PMONITOR )
return ;
2022-03-19 13:35:04 +01:00
// Render layer surfaces below windows for monitor
for ( auto & ls : PMONITOR - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , PMONITOR , time ) ;
2022-03-19 13:35:04 +01:00
}
for ( auto & ls : PMONITOR - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , PMONITOR , time ) ;
2022-03-19 13:35:04 +01:00
}
2022-08-01 12:23:09 +02:00
// pre window pass
g_pHyprOpenGL - > preWindowPass ( ) ;
2022-03-21 19:18:33 +01:00
// if there is a fullscreen window, render it and then do not render anymore.
// fullscreen window will hide other windows and top layers
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( PMONITOR - > activeWorkspace ) ;
2022-03-18 20:03:39 +01:00
2022-04-11 19:51:37 +02:00
if ( PWORKSPACE - > m_bHasFullscreenWindow ) {
2022-03-21 19:18:33 +01:00
renderWorkspaceWithFullscreenWindow ( PMONITOR , PWORKSPACE , time ) ;
return ;
2022-03-17 20:22:29 +01:00
}
2022-03-18 20:03:39 +01:00
2022-07-12 09:49:56 +02:00
// Non-floating main
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bHidden & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
if ( w - > m_bIsFloating )
continue ; // floating are in the second pass
if ( w - > m_iWorkspaceID = = SPECIAL_WORKSPACE_ID )
continue ; // special are in the third pass
if ( ! shouldRenderWindow ( w . get ( ) , PMONITOR ) )
continue ;
// render the bad boy
renderWindow ( w . get ( ) , PMONITOR , time , true , RENDER_PASS_MAIN ) ;
}
// Non-floating popup
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bHidden & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
2022-03-18 23:52:36 +01:00
continue ;
2022-06-30 15:44:26 +02:00
if ( w - > m_bIsFloating )
2022-05-31 14:01:00 +02:00
continue ; // floating are in the second pass
2022-06-30 15:44:26 +02:00
if ( w - > m_iWorkspaceID = = SPECIAL_WORKSPACE_ID )
2022-05-31 14:01:00 +02:00
continue ; // special are in the third pass
2022-03-22 17:14:07 +01:00
2022-06-30 15:44:26 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , PMONITOR ) )
2022-03-22 17:14:07 +01:00
continue ;
// render the bad boy
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , PMONITOR , time , true , RENDER_PASS_POPUP ) ;
2022-03-22 17:14:07 +01:00
}
// floating on top
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bHidden & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
2022-03-22 17:14:07 +01:00
continue ;
2022-06-30 15:44:26 +02:00
if ( ! w - > m_bIsFloating )
2022-03-22 17:14:07 +01:00
continue ;
2022-06-30 15:44:26 +02:00
if ( w - > m_iWorkspaceID = = SPECIAL_WORKSPACE_ID )
2022-05-31 14:01:00 +02:00
continue ;
2022-06-30 15:44:26 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , PMONITOR ) )
2022-05-31 14:01:00 +02:00
continue ;
// render the bad boy
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , PMONITOR , time , true , RENDER_PASS_ALL ) ;
2022-05-31 14:01:00 +02:00
}
// and then special
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bHidden & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
2022-05-31 14:01:00 +02:00
continue ;
2022-06-30 15:44:26 +02:00
if ( w - > m_iWorkspaceID ! = SPECIAL_WORKSPACE_ID )
2022-05-31 14:01:00 +02:00
continue ;
2022-06-30 15:44:26 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , PMONITOR ) )
2022-03-18 20:03:39 +01:00
continue ;
2022-03-18 20:42:49 +01:00
// render the bad boy
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , PMONITOR , time , true , RENDER_PASS_ALL ) ;
2022-03-18 20:03:39 +01:00
}
2022-03-19 13:35:04 +01:00
// Render surfaces above windows for monitor
for ( auto & ls : PMONITOR - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_TOP ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , PMONITOR , time ) ;
2022-03-19 13:35:04 +01:00
}
2022-08-05 17:07:01 +02:00
// Render IME popups
for ( auto & imep : g_pInputManager - > m_sIMERelay . m_lIMEPopups ) {
renderIMEPopup ( & imep , PMONITOR , time ) ;
}
2022-03-19 13:35:04 +01:00
for ( auto & ls : PMONITOR - > m_aLayerSurfaceLists [ ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ] ) {
2022-07-23 15:48:08 +02:00
renderLayer ( ls . get ( ) , PMONITOR , time ) ;
2022-03-19 13:35:04 +01:00
}
2022-03-31 17:25:23 +02:00
renderDragIcon ( PMONITOR , time ) ;
2022-03-17 20:22:29 +01:00
}
2022-03-19 14:07:18 +01:00
void CHyprRenderer : : outputMgrApplyTest ( wlr_output_configuration_v1 * config , bool test ) {
wlr_output_configuration_head_v1 * head ;
bool noError = true ;
wl_list_for_each ( head , & config - > heads , link ) {
2022-05-06 17:18:24 +02:00
std : : string commandForCfg = " " ;
2022-03-19 14:07:18 +01:00
const auto OUTPUT = head - > state . output ;
2022-05-06 17:18:24 +02:00
commandForCfg + = std : : string ( OUTPUT - > name ) + " , " ;
if ( ! head - > state . enabled ) {
commandForCfg + = " disabled " ;
if ( ! test )
g_pConfigManager - > parseKeyword ( " monitor " , commandForCfg , true ) ;
continue ;
2022-03-19 14:07:18 +01:00
}
2022-05-06 17:18:24 +02:00
wlr_output_enable ( OUTPUT , head - > state . enabled ) ;
if ( head - > state . mode )
commandForCfg + = std : : to_string ( head - > state . mode - > width ) + " x " + std : : to_string ( head - > state . mode - > height ) + " @ " + std : : to_string ( head - > state . mode - > refresh / 1000.f ) + " , " ;
else
commandForCfg + = std : : to_string ( head - > state . custom_mode . width ) + " x " + std : : to_string ( head - > state . custom_mode . height ) + " @ " + std : : to_string ( head - > state . custom_mode . refresh / 1000.f ) + " , " ;
commandForCfg + = std : : to_string ( head - > state . x ) + " x " + std : : to_string ( head - > state . y ) + " , " + std : : to_string ( head - > state . scale ) ;
if ( ! test )
g_pConfigManager - > parseKeyword ( " monitor " , commandForCfg , true ) ;
2022-03-19 14:07:18 +01:00
noError = wlr_output_test ( OUTPUT ) ;
if ( ! noError )
break ;
}
2022-05-06 17:18:24 +02:00
if ( ! test )
g_pConfigManager - > m_bWantsMonitorReload = true ; // for monitor keywords
2022-03-19 14:07:18 +01:00
if ( noError )
wlr_output_configuration_v1_send_succeeded ( config ) ;
else
wlr_output_configuration_v1_send_failed ( config ) ;
wlr_output_configuration_v1_destroy ( config ) ;
Debug : : log ( LOG , " OutputMgr Applied/Tested. " ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// taken from Sway.
// this is just too much of a spaghetti for me to understand
void apply_exclusive ( struct wlr_box * usable_area , uint32_t anchor , int32_t exclusive , int32_t margin_top , int32_t margin_right , int32_t margin_bottom , int32_t margin_left ) {
if ( exclusive < = 0 ) {
return ;
}
struct {
uint32_t singular_anchor ;
uint32_t anchor_triplet ;
int * positive_axis ;
int * negative_axis ;
int margin ;
} edges [ ] = {
// Top
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ,
. anchor_triplet =
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ,
. positive_axis = & usable_area - > y ,
. negative_axis = & usable_area - > height ,
. margin = margin_top ,
} ,
// Bottom
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. anchor_triplet =
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = NULL ,
. negative_axis = & usable_area - > height ,
. margin = margin_bottom ,
} ,
// Left
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ,
. anchor_triplet =
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = & usable_area - > x ,
. negative_axis = & usable_area - > width ,
. margin = margin_left ,
} ,
// Right
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ,
. anchor_triplet =
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = NULL ,
. negative_axis = & usable_area - > width ,
. margin = margin_right ,
} ,
} ;
for ( size_t i = 0 ; i < sizeof ( edges ) / sizeof ( edges [ 0 ] ) ; + + i ) {
if ( ( anchor = = edges [ i ] . singular_anchor | | anchor = = edges [ i ] . anchor_triplet ) & & exclusive + edges [ i ] . margin > 0 ) {
if ( edges [ i ] . positive_axis ) {
* edges [ i ] . positive_axis + = exclusive + edges [ i ] . margin ;
}
if ( edges [ i ] . negative_axis ) {
* edges [ i ] . negative_axis - = exclusive + edges [ i ] . margin ;
}
break ;
}
}
}
2022-03-19 14:37:40 +01:00
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : arrangeLayerArray ( CMonitor * pMonitor , const std : : vector < std : : unique_ptr < SLayerSurface > > & layerSurfaces , bool exclusiveZone , wlr_box * usableArea ) {
2022-03-21 17:00:17 +01:00
wlr_box full_area = { pMonitor - > vecPosition . x , pMonitor - > vecPosition . y , pMonitor - > vecSize . x , pMonitor - > vecSize . y } ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:00:17 +01:00
for ( auto & ls : layerSurfaces ) {
2022-07-18 21:16:01 +02:00
if ( ls - > fadingOut | | ls - > readyToDelete | | ! ls - > layerSurface | | ls - > noProcess )
2022-05-14 17:23:46 +02:00
continue ;
2022-03-21 17:00:17 +01:00
const auto PLAYER = ls - > layerSurface ;
const auto PSTATE = & PLAYER - > current ;
if ( exclusiveZone ! = ( PSTATE - > exclusive_zone > 0 ) ) {
continue ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
wlr_box bounds ;
if ( PSTATE - > exclusive_zone = = - 1 ) {
bounds = full_area ;
} else {
bounds = * usableArea ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
wlr_box box = {
. width = PSTATE - > desired_width ,
. height = PSTATE - > desired_height } ;
// Horizontal axis
const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ;
if ( box . width = = 0 ) {
box . x = bounds . x ;
} else if ( ( PSTATE - > anchor & both_horiz ) = = both_horiz ) {
box . x = bounds . x + ( ( bounds . width / 2 ) - ( box . width / 2 ) ) ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ) ) {
box . x = bounds . x ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ) ) {
box . x = bounds . x + ( bounds . width - box . width ) ;
} else {
box . x = bounds . x + ( ( bounds . width / 2 ) - ( box . width / 2 ) ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// Vertical axis
const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ;
if ( box . height = = 0 ) {
box . y = bounds . y ;
} else if ( ( PSTATE - > anchor & both_vert ) = = both_vert ) {
box . y = bounds . y + ( ( bounds . height / 2 ) - ( box . height / 2 ) ) ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ) ) {
box . y = bounds . y ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ) ) {
box . y = bounds . y + ( bounds . height - box . height ) ;
} else {
box . y = bounds . y + ( ( bounds . height / 2 ) - ( box . height / 2 ) ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// Margin
if ( box . width = = 0 ) {
box . x + = PSTATE - > margin . left ;
box . width = bounds . width -
( PSTATE - > margin . left + PSTATE - > margin . right ) ;
} else if ( ( PSTATE - > anchor & both_horiz ) = = both_horiz ) {
// don't apply margins
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ) ) {
box . x + = PSTATE - > margin . left ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ) ) {
box . x - = PSTATE - > margin . right ;
}
if ( box . height = = 0 ) {
box . y + = PSTATE - > margin . top ;
box . height = bounds . height -
( PSTATE - > margin . top + PSTATE - > margin . bottom ) ;
} else if ( ( PSTATE - > anchor & both_vert ) = = both_vert ) {
// don't apply margins
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ) ) {
box . y + = PSTATE - > margin . top ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ) ) {
box . y - = PSTATE - > margin . bottom ;
}
if ( box . width < = 0 | | box . height < = 0 ) {
2022-07-23 15:48:08 +02:00
Debug : : log ( ERR , " LayerSurface %x has a negative/zero w/h??? " , ls . get ( ) ) ;
2022-03-21 17:00:17 +01:00
continue ;
2022-03-20 14:52:23 +01:00
}
2022-03-21 17:00:17 +01:00
// Apply
ls - > geometry = box ;
2022-03-20 14:52:23 +01:00
2022-03-21 17:00:17 +01:00
apply_exclusive ( usableArea , PSTATE - > anchor , PSTATE - > exclusive_zone , PSTATE - > margin . top , PSTATE - > margin . right , PSTATE - > margin . bottom , PSTATE - > margin . left ) ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:00:17 +01:00
wlr_layer_surface_v1_configure ( ls - > layerSurface , box . width , box . height ) ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:50:28 +01:00
Debug : : log ( LOG , " LayerSurface %x arranged: x: %i y: %i w: %i h: %i with margins: t: %i l: %i r: %i b: %i " , & ls , box . x , box . y , box . width , box . height , PSTATE - > margin . top , PSTATE - > margin . left , PSTATE - > margin . right , PSTATE - > margin . bottom ) ;
2022-03-19 14:37:40 +01:00
}
}
void CHyprRenderer : : arrangeLayersForMonitor ( const int & monitor ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( monitor ) ;
if ( ! PMONITOR )
return ;
// Reset the reserved
PMONITOR - > vecReservedBottomRight = Vector2D ( ) ;
PMONITOR - > vecReservedTopLeft = Vector2D ( ) ;
2022-03-21 17:00:17 +01:00
wlr_box usableArea = { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
for ( auto & la : PMONITOR - > m_aLayerSurfaceLists )
arrangeLayerArray ( PMONITOR , la , true , & usableArea ) ;
2022-03-19 14:37:40 +01:00
for ( auto & la : PMONITOR - > m_aLayerSurfaceLists )
2022-03-21 17:00:17 +01:00
arrangeLayerArray ( PMONITOR , la , false , & usableArea ) ;
PMONITOR - > vecReservedTopLeft = Vector2D ( usableArea . x , usableArea . y ) - PMONITOR - > vecPosition ;
PMONITOR - > vecReservedBottomRight = PMONITOR - > vecSize - Vector2D ( usableArea . width , usableArea . height ) - PMONITOR - > vecReservedTopLeft ;
2022-04-27 17:46:07 +02:00
const auto ENTRY = g_pConfigManager - > m_mAdditionalReservedAreas [ PMONITOR - > szName ] ;
PMONITOR - > vecReservedTopLeft = PMONITOR - > vecReservedTopLeft + Vector2D ( ENTRY . left , ENTRY . top ) ;
PMONITOR - > vecReservedBottomRight = PMONITOR - > vecReservedBottomRight + Vector2D ( ENTRY . right , ENTRY . bottom ) ;
2022-05-04 15:23:30 +02:00
// damage the monitor if can
if ( PMONITOR - > damage )
damageMonitor ( PMONITOR ) ;
2022-03-21 17:26:02 +01:00
Debug : : log ( LOG , " Monitor %s layers arranged: reserved: %f %f %f %f " , PMONITOR - > szName . c_str ( ) , PMONITOR - > vecReservedTopLeft . x , PMONITOR - > vecReservedTopLeft . y , PMONITOR - > vecReservedBottomRight . x , PMONITOR - > vecReservedBottomRight . y ) ;
2022-03-19 16:13:19 +01:00
}
2022-04-14 16:43:29 +02:00
void CHyprRenderer : : damageSurface ( wlr_surface * pSurface , double x , double y ) {
if ( ! pSurface )
return ; // wut?
2022-03-21 16:13:43 +01:00
2022-04-14 16:43:29 +02:00
pixman_region32_t damageBox ;
pixman_region32_init ( & damageBox ) ;
wlr_surface_get_effective_damage ( pSurface , & damageBox ) ;
2022-03-21 16:13:43 +01:00
2022-07-04 17:55:33 +02:00
// schedule frame events
if ( ! wl_list_empty ( & pSurface - > current . frame_callback_list ) ) {
2022-07-13 18:18:23 +02:00
g_pCompositor - > scheduleFrameForMonitor ( g_pCompositor - > getMonitorFromVector ( Vector2D ( x , y ) ) ) ;
2022-07-04 17:55:33 +02:00
}
2022-06-28 15:30:46 +02:00
if ( ! pixman_region32_not_empty ( & damageBox ) ) {
pixman_region32_fini ( & damageBox ) ;
return ;
}
2022-07-28 22:15:56 +02:00
pixman_region32_t damageBoxForEach ;
pixman_region32_init ( & damageBoxForEach ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
2022-04-14 16:43:29 +02:00
double lx = 0 , ly = 0 ;
2022-06-30 15:44:26 +02:00
wlr_output_layout_output_coords ( g_pCompositor - > m_sWLROutputLayout , m - > output , & lx , & ly ) ;
2022-07-28 22:15:56 +02:00
2022-07-28 23:21:35 +02:00
pixman_region32_copy ( & damageBoxForEach , & damageBox ) ;
2022-07-29 11:52:56 +02:00
pixman_region32_translate ( & damageBoxForEach , x - m - > vecPosition . x , y - m - > vecPosition . y ) ;
2022-07-28 23:21:35 +02:00
wlr_region_scale ( & damageBoxForEach , & damageBoxForEach , m - > scale ) ;
2022-07-29 11:52:56 +02:00
pixman_region32_translate ( & damageBoxForEach , lx + m - > vecPosition . x , ly + m - > vecPosition . y ) ;
2022-07-28 22:15:56 +02:00
2022-07-28 22:23:27 +02:00
wlr_output_damage_add ( m - > damage , & damageBoxForEach ) ;
2022-03-21 16:13:43 +01:00
}
2022-07-28 22:15:56 +02:00
pixman_region32_fini ( & damageBoxForEach ) ;
2022-06-07 20:41:40 +02:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
if ( * PLOGDAMAGE )
2022-05-05 15:09:26 +02:00
Debug : : log ( LOG , " Damage: Surface (extents): xy: %d, %d wh: %d, %d " , damageBox . extents . x1 , damageBox . extents . y1 , damageBox . extents . x2 - damageBox . extents . x1 , damageBox . extents . y2 - damageBox . extents . y1 ) ;
2022-07-20 12:06:14 +02:00
pixman_region32_fini ( & damageBox ) ;
2022-04-14 16:43:29 +02:00
}
2022-03-21 16:13:43 +01:00
2022-04-14 16:43:29 +02:00
void CHyprRenderer : : damageWindow ( CWindow * pWindow ) {
2022-06-29 11:21:42 +02:00
wlr_box damageBox = pWindow - > getFullWindowBoundingBox ( ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
wlr_box fixedDamageBox = { damageBox . x - m - > vecPosition . x , damageBox . y - m - > vecPosition . y , damageBox . width , damageBox . height } ;
scaleBox ( & fixedDamageBox , m - > scale ) ;
wlr_output_damage_add_box ( m - > damage , & fixedDamageBox ) ;
2022-06-29 11:21:42 +02:00
}
2022-05-05 15:09:26 +02:00
2022-06-29 11:21:42 +02:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
2022-06-07 20:41:40 +02:00
2022-06-29 11:21:42 +02:00
if ( * PLOGDAMAGE )
Debug : : log ( LOG , " Damage: Window (%s): xy: %d, %d wh: %d, %d " , pWindow - > m_szTitle . c_str ( ) , damageBox . x , damageBox . y , damageBox . width , damageBox . height ) ;
2022-03-21 16:13:43 +01:00
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : damageMonitor ( CMonitor * pMonitor ) {
2022-05-18 20:33:54 +02:00
wlr_box damageBox = { 0 , 0 , pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y } ;
2022-04-14 16:43:29 +02:00
wlr_output_damage_add_box ( pMonitor - > damage , & damageBox ) ;
2022-05-05 15:09:26 +02:00
2022-06-07 20:41:40 +02:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
if ( * PLOGDAMAGE )
2022-05-05 15:09:26 +02:00
Debug : : log ( LOG , " Damage: Monitor %s " , pMonitor - > szName . c_str ( ) ) ;
2022-04-14 16:43:29 +02:00
}
2022-03-21 16:13:43 +01:00
2022-04-14 16:43:29 +02:00
void CHyprRenderer : : damageBox ( wlr_box * pBox ) {
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
wlr_box damageBox = { pBox - > x - m - > vecPosition . x , pBox - > y - m - > vecPosition . y , pBox - > width , pBox - > height } ;
scaleBox ( & damageBox , m - > scale ) ;
wlr_output_damage_add_box ( m - > damage , & damageBox ) ;
2022-04-17 18:47:10 +02:00
}
2022-05-05 15:09:26 +02:00
2022-06-07 20:41:40 +02:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
if ( * PLOGDAMAGE )
2022-05-05 15:09:26 +02:00
Debug : : log ( LOG , " Damage: Box: xy: %d, %d wh: %d, %d " , pBox - > x , pBox - > y , pBox - > width , pBox - > height ) ;
2022-03-31 17:25:23 +02:00
}
2022-05-05 14:02:30 +02:00
void CHyprRenderer : : damageBox ( const int & x , const int & y , const int & w , const int & h ) {
wlr_box box = { x , y , w , h } ;
damageBox ( & box ) ;
}
2022-07-16 12:44:45 +02:00
void CHyprRenderer : : damageRegion ( pixman_region32_t * rg ) {
PIXMAN_DAMAGE_FOREACH ( rg ) {
const auto RECT = RECTSARR [ i ] ;
damageBox ( RECT . x1 , RECT . y1 , RECT . x2 - RECT . x1 , RECT . y2 - RECT . y1 ) ;
}
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderDragIcon ( CMonitor * pMonitor , timespec * time ) {
2022-03-31 17:25:23 +02:00
if ( ! ( g_pInputManager - > m_sDrag . dragIcon & & g_pInputManager - > m_sDrag . iconMapped & & g_pInputManager - > m_sDrag . dragIcon - > surface ) )
return ;
SRenderData renderdata = { pMonitor - > output , time , g_pInputManager - > m_sDrag . pos . x , g_pInputManager - > m_sDrag . pos . y } ;
renderdata . surface = g_pInputManager - > m_sDrag . dragIcon - > surface ;
renderdata . w = g_pInputManager - > m_sDrag . dragIcon - > surface - > current . width ;
renderdata . h = g_pInputManager - > m_sDrag . dragIcon - > surface - > current . height ;
wlr_surface_for_each_surface ( g_pInputManager - > m_sDrag . dragIcon - > surface , renderSurface , & renderdata ) ;
2022-06-29 14:15:08 +02:00
wlr_box box = { g_pInputManager - > m_sDrag . pos . x - 2 , g_pInputManager - > m_sDrag . pos . y - 2 , g_pInputManager - > m_sDrag . dragIcon - > surface - > current . width + 4 , g_pInputManager - > m_sDrag . dragIcon - > surface - > current . height + 4 } ;
g_pHyprRenderer - > damageBox ( & box ) ;
2022-04-14 16:43:29 +02:00
}
DAMAGETRACKINGMODES CHyprRenderer : : damageTrackingModeFromStr ( const std : : string & mode ) {
if ( mode = = " full " )
return DAMAGE_TRACKING_FULL ;
if ( mode = = " monitor " )
return DAMAGE_TRACKING_MONITOR ;
if ( mode = = " none " )
return DAMAGE_TRACKING_NONE ;
return DAMAGE_TRACKING_INVALID ;
2022-04-19 19:01:23 +02:00
}
2022-07-27 12:32:00 +02:00
bool CHyprRenderer : : applyMonitorRule ( CMonitor * pMonitor , SMonitorRule * pMonitorRule , bool force ) {
2022-04-19 19:01:23 +02:00
2022-04-21 18:11:28 +02:00
Debug : : log ( LOG , " Applying monitor rule for %s " , pMonitor - > szName . c_str ( ) ) ;
2022-06-30 23:50:57 +02:00
// if it's disabled, disable and ignore
if ( pMonitorRule - > disabled ) {
2022-07-27 12:32:00 +02:00
if ( pMonitor - > m_bEnabled )
pMonitor - > onDisconnect ( ) ;
2022-08-03 17:32:12 +02:00
return true ;
2022-06-30 23:50:57 +02:00
}
2022-07-27 12:32:00 +02:00
if ( ! pMonitor - > m_bEnabled ) {
pMonitor - > onConnect ( true ) ; // enable it.
force = true ;
}
2022-04-19 19:01:23 +02:00
// Check if the rule isn't already applied
2022-08-04 11:10:26 +02:00
if ( ! force
& & DELTALESSTHAN ( pMonitor - > vecPixelSize . x , pMonitorRule - > resolution . x , 1 )
& & DELTALESSTHAN ( pMonitor - > vecPixelSize . y , pMonitorRule - > resolution . y , 1 )
& & DELTALESSTHAN ( pMonitor - > refreshRate , pMonitorRule - > refreshRate , 1 )
& & pMonitor - > scale = = pMonitorRule - > scale
& & ( ( DELTALESSTHAN ( pMonitor - > vecPosition . x , pMonitorRule - > offset . x , 1 ) & & DELTALESSTHAN ( pMonitor - > vecPosition . y , pMonitorRule - > offset . y , 1 ) ) | | pMonitorRule - > offset = = Vector2D ( - 1 , - 1 ) )
& & pMonitor - > transform = = pMonitorRule - > transform ) {
2022-04-19 19:01:23 +02:00
Debug : : log ( LOG , " Not applying a new rule to %s because it's already applied! " , pMonitor - > szName . c_str ( ) ) ;
2022-06-30 23:55:28 +02:00
return true ;
2022-04-19 19:01:23 +02:00
}
wlr_output_set_scale ( pMonitor - > output , pMonitorRule - > scale ) ;
pMonitor - > scale = pMonitorRule - > scale ;
2022-05-27 10:27:06 +02:00
pMonitor - > vecPosition = pMonitorRule - > offset ;
2022-04-19 19:01:23 +02:00
// loop over modes and choose an appropriate one.
2022-07-30 22:54:29 +02:00
if ( pMonitorRule - > resolution ! = Vector2D ( ) ) {
if ( ! wl_list_empty ( & pMonitor - > output - > modes ) ) {
wlr_output_mode * mode ;
bool found = false ;
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
if ( DELTALESSTHAN ( mode - > width , pMonitorRule - > resolution . x , 1 ) & & DELTALESSTHAN ( mode - > height , pMonitorRule - > resolution . y , 1 ) & & DELTALESSTHAN ( mode - > refresh / 1000.f , pMonitorRule - > refreshRate , 1 ) ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( ! wlr_output_test ( pMonitor - > output ) ) {
Debug : : log ( LOG , " Monitor %s: REJECTED available mode: %ix%i@%2f! " ,
pMonitor - > output - > name , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ,
mode - > width , mode - > height , mode - > refresh / 1000.f ) ;
continue ;
}
Debug : : log ( LOG , " Monitor %s: requested %ix%i@%2f, found available mode: %ix%i@%imHz, applying. " ,
2022-04-19 19:01:23 +02:00
pMonitor - > output - > name , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ,
2022-07-30 22:54:29 +02:00
mode - > width , mode - > height , mode - > refresh ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
found = true ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
pMonitor - > refreshRate = mode - > refresh / 1000.f ;
pMonitor - > vecSize = Vector2D ( mode - > width , mode - > height ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
break ;
}
2022-04-19 19:01:23 +02:00
}
2022-07-30 22:54:29 +02:00
if ( ! found ) {
wlr_output_set_custom_mode ( pMonitor - > output , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( int ) pMonitorRule - > refreshRate * 1000 ) ;
pMonitor - > vecSize = pMonitorRule - > resolution ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
if ( ! wlr_output_test ( pMonitor - > output ) ) {
Debug : : log ( ERR , " Custom resolution FAILED, falling back to preferred " ) ;
2022-06-28 11:12:01 +02:00
2022-07-30 22:54:29 +02:00
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
2022-06-28 11:12:01 +02:00
2022-07-30 22:54:29 +02:00
if ( ! PREFERREDMODE ) {
Debug : : log ( ERR , " Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f " ,
( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ) ;
return true ;
}
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
Debug : : log ( ERR , " Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f " ,
pMonitor - > output - > name , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ,
PREFERREDMODE - > width , PREFERREDMODE - > height , PREFERREDMODE - > refresh / 1000.f ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
} else {
Debug : : log ( LOG , " Set a custom mode %ix%i@%2f (mode not found in monitor modes) " , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ) ;
}
2022-06-28 11:12:01 +02:00
}
2022-07-30 22:54:29 +02:00
} else {
wlr_output_set_custom_mode ( pMonitor - > output , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( int ) pMonitorRule - > refreshRate * 1000 ) ;
pMonitor - > vecSize = pMonitorRule - > resolution ;
2022-08-07 19:28:31 +02:00
Debug : : log ( LOG , " Setting custom mode for %s " , pMonitor - > output - > name ) ;
2022-04-19 19:01:23 +02:00
}
} else {
2022-07-30 22:54:29 +02:00
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
if ( ! PREFERREDMODE ) {
Debug : : log ( ERR , " Monitor %s has NO PREFERRED MODE " ,
( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ) ;
2022-08-02 22:20:45 +02:00
if ( ! wl_list_empty ( & pMonitor - > output - > modes ) ) {
wlr_output_mode * mode ;
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( ! wlr_output_test ( pMonitor - > output ) ) {
Debug : : log ( LOG , " Monitor %s: REJECTED available mode: %ix%i@%2f! " ,
pMonitor - > output - > name , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ,
mode - > width , mode - > height , mode - > refresh / 1000.f ) ;
continue ;
}
Debug : : log ( LOG , " Monitor %s: requested %ix%i@%2f, found available mode: %ix%i@%imHz, applying. " ,
pMonitor - > output - > name , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , ( float ) pMonitorRule - > refreshRate ,
mode - > width , mode - > height , mode - > refresh ) ;
pMonitor - > refreshRate = mode - > refresh / 1000.f ;
pMonitor - > vecSize = Vector2D ( mode - > width , mode - > height ) ;
break ;
}
}
} else {
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
2022-08-07 19:28:31 +02:00
Debug : : log ( LOG , " Setting preferred mode for %s " , pMonitor - > output - > name ) ;
2022-08-02 22:20:45 +02:00
}
2022-04-19 19:01:23 +02:00
}
2022-07-30 22:54:29 +02:00
2022-04-19 19:01:23 +02:00
2022-05-29 12:27:45 +02:00
wlr_output_set_transform ( pMonitor - > output , pMonitorRule - > transform ) ;
pMonitor - > transform = pMonitorRule - > transform ;
2022-05-18 20:33:54 +02:00
pMonitor - > vecPixelSize = pMonitor - > vecSize ;
2022-04-19 19:01:23 +02:00
// update renderer
g_pHyprOpenGL - > destroyMonitorResources ( pMonitor ) ;
if ( ! wlr_output_commit ( pMonitor - > output ) ) {
Debug : : log ( ERR , " Couldn't commit output named %s " , pMonitor - > output - > name ) ;
2022-06-30 23:55:28 +02:00
return true ;
2022-04-19 19:01:23 +02:00
}
2022-04-21 18:11:28 +02:00
2022-05-29 12:27:45 +02:00
int x , y ;
wlr_output_transformed_resolution ( pMonitor - > output , & x , & y ) ;
pMonitor - > vecSize = ( Vector2D ( x , y ) / pMonitor - > scale ) . floor ( ) ;
pMonitor - > vecTransformedSize = Vector2D ( x , y ) ;
2022-08-04 11:10:26 +02:00
if ( pMonitorRule - > offset = = Vector2D ( - 1 , - 1 ) ) {
// let's find manually a sensible position for it, to the right.
Vector2D finalPos ;
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( m - > ID = = pMonitor - > ID )
continue ;
if ( m - > vecPosition . x + std : : ceil ( m - > vecSize . x ) > finalPos . x ) {
finalPos . x = m - > vecPosition . x + std : : ceil ( m - > vecSize . x ) ;
}
}
pMonitor - > vecPosition = finalPos ;
}
2022-04-21 18:11:28 +02:00
2022-08-04 11:10:26 +02:00
wlr_output_layout_add ( g_pCompositor - > m_sWLROutputLayout , pMonitor - > output , ( int ) pMonitor - > vecPosition . x , ( int ) pMonitor - > vecPosition . y ) ;
2022-04-21 18:11:28 +02:00
wlr_output_enable ( pMonitor - > output , true ) ;
// updato wlroots
Events : : listener_change ( nullptr , nullptr ) ;
// updato us
arrangeLayersForMonitor ( pMonitor - > ID ) ;
// frame skip
2022-06-06 13:48:17 +02:00
pMonitor - > framesToSkip = 1 ;
2022-06-30 23:55:28 +02:00
return true ;
2022-04-21 18:11:28 +02:00
}
2022-06-24 23:27:02 +02:00
void CHyprRenderer : : ensureCursorRenderingMode ( ) {
static auto * const PCURSORTIMEOUT = & g_pConfigManager - > getConfigValuePtr ( " general:cursor_inactive_timeout " ) - > intValue ;
const auto PASSEDCURSORSECONDS = g_pInputManager - > m_tmrLastCursorMovement . getSeconds ( ) ;
if ( * PCURSORTIMEOUT > 0 ) {
if ( * PCURSORTIMEOUT < PASSEDCURSORSECONDS & & m_bHasARenderedCursor ) {
m_bHasARenderedCursor = false ;
wlr_cursor_set_surface ( g_pCompositor - > m_sWLRCursor , nullptr , 0 , 0 ) ; // hide
Debug : : log ( LOG , " Hiding the cursor (timeout) " ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ; // TODO: maybe just damage the cursor area?
2022-06-24 23:27:02 +02:00
} else if ( * PCURSORTIMEOUT > PASSEDCURSORSECONDS & & ! m_bHasARenderedCursor ) {
m_bHasARenderedCursor = true ;
2022-06-26 13:43:32 +02:00
if ( ! m_bWindowRequestedCursorHide )
wlr_xcursor_manager_set_cursor_image ( g_pCompositor - > m_sWLRXCursorMgr , " left_ptr " , g_pCompositor - > m_sWLRCursor ) ;
2022-06-24 23:27:02 +02:00
Debug : : log ( LOG , " Showing the cursor (timeout) " ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ; // TODO: maybe just damage the cursor area?
2022-06-24 23:27:02 +02:00
}
} else {
m_bHasARenderedCursor = true ;
}
2022-06-26 13:43:32 +02:00
}
bool CHyprRenderer : : shouldRenderCursor ( ) {
return m_bHasARenderedCursor ;
2022-07-11 23:38:10 +02:00
}