2022-03-30 21:18:42 +02:00
# include "Window.hpp"
# include "Compositor.hpp"
2022-06-25 20:28:40 +02:00
# include "render/decorations/CHyprDropShadowDecoration.hpp"
2022-03-30 21:18:42 +02:00
2022-04-23 14:16:02 +02:00
CWindow : : CWindow ( ) {
2022-11-04 16:56:31 +01:00
m_vRealPosition . create ( AVARTYPE_VECTOR , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , ( void * ) this , AVARDAMAGE_ENTIRE ) ;
2022-07-28 13:28:43 +02:00
m_vRealSize . create ( AVARTYPE_VECTOR , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , ( void * ) this , AVARDAMAGE_ENTIRE ) ;
m_cRealBorderColor . create ( AVARTYPE_COLOR , g_pConfigManager - > getAnimationPropertyConfig ( " border " ) , ( void * ) this , AVARDAMAGE_BORDER ) ;
m_fAlpha . create ( AVARTYPE_FLOAT , g_pConfigManager - > getAnimationPropertyConfig ( " fadeIn " ) , ( void * ) this , AVARDAMAGE_ENTIRE ) ;
m_fActiveInactiveAlpha . create ( AVARTYPE_FLOAT , g_pConfigManager - > getAnimationPropertyConfig ( " fadeSwitch " ) , ( void * ) this , AVARDAMAGE_ENTIRE ) ;
m_cRealShadowColor . create ( AVARTYPE_COLOR , g_pConfigManager - > getAnimationPropertyConfig ( " fadeShadow " ) , ( void * ) this , AVARDAMAGE_SHADOW ) ;
2022-08-30 12:46:17 +02:00
m_fDimPercent . create ( AVARTYPE_FLOAT , g_pConfigManager - > getAnimationPropertyConfig ( " fadeDim " ) , ( void * ) this , AVARDAMAGE_ENTIRE ) ;
2022-06-25 20:28:40 +02:00
m_dWindowDecorations . emplace_back ( std : : make_unique < CHyprDropShadowDecoration > ( this ) ) ; // put the shadow so it's the first deco (has to be rendered first)
2022-04-23 14:16:02 +02:00
}
2022-03-30 21:18:42 +02:00
CWindow : : ~ CWindow ( ) {
2022-04-02 18:57:09 +02:00
if ( g_pCompositor - > isWindowActive ( this ) ) {
2022-03-30 21:18:42 +02:00
g_pCompositor - > m_pLastFocus = nullptr ;
2022-04-02 18:57:09 +02:00
g_pCompositor - > m_pLastWindow = nullptr ;
}
2022-05-30 14:55:42 +02:00
}
wlr_box CWindow : : getFullWindowBoundingBox ( ) {
2022-08-27 21:37:35 +02:00
static auto * const PBORDERSIZE = & g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
2022-05-30 14:55:42 +02:00
2022-08-24 13:44:48 +02:00
SWindowDecorationExtents maxExtents = { { * PBORDERSIZE + 2 , * PBORDERSIZE + 2 } , { * PBORDERSIZE + 2 , * PBORDERSIZE + 2 } } ;
2022-05-30 14:55:42 +02:00
for ( auto & wd : m_dWindowDecorations ) {
const auto EXTENTS = wd - > getWindowDecorationExtents ( ) ;
if ( EXTENTS . topLeft . x > maxExtents . topLeft . x )
maxExtents . topLeft . x = EXTENTS . topLeft . x ;
if ( EXTENTS . topLeft . y > maxExtents . topLeft . y )
maxExtents . topLeft . y = EXTENTS . topLeft . y ;
if ( EXTENTS . bottomRight . x > maxExtents . bottomRight . x )
maxExtents . bottomRight . x = EXTENTS . bottomRight . x ;
if ( EXTENTS . bottomRight . y > maxExtents . bottomRight . y )
maxExtents . bottomRight . y = EXTENTS . bottomRight . y ;
}
// Add extents to the real base BB and return
wlr_box finalBox = { m_vRealPosition . vec ( ) . x - maxExtents . topLeft . x ,
m_vRealPosition . vec ( ) . y - maxExtents . topLeft . y ,
m_vRealSize . vec ( ) . x + maxExtents . topLeft . x + maxExtents . bottomRight . x ,
m_vRealSize . vec ( ) . y + maxExtents . topLeft . y + maxExtents . bottomRight . y } ;
2022-09-25 20:07:48 +02:00
2022-05-30 14:55:42 +02:00
return finalBox ;
2022-06-23 20:39:48 +02:00
}
wlr_box CWindow : : getWindowIdealBoundingBoxIgnoreReserved ( ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
auto POS = m_vPosition ;
auto SIZE = m_vSize ;
if ( DELTALESSTHAN ( POS . y - PMONITOR - > vecPosition . y , PMONITOR - > vecReservedTopLeft . y , 1 ) ) {
POS . y = PMONITOR - > vecPosition . y ;
SIZE . y + = PMONITOR - > vecReservedTopLeft . y ;
}
if ( DELTALESSTHAN ( POS . x - PMONITOR - > vecPosition . x , PMONITOR - > vecReservedTopLeft . x , 1 ) ) {
POS . x = PMONITOR - > vecPosition . x ;
SIZE . x + = PMONITOR - > vecReservedTopLeft . x ;
}
if ( DELTALESSTHAN ( POS . x + SIZE . x - PMONITOR - > vecPosition . x , PMONITOR - > vecSize . x - PMONITOR - > vecReservedBottomRight . x , 1 ) ) {
SIZE . x + = PMONITOR - > vecReservedBottomRight . x ;
}
if ( DELTALESSTHAN ( POS . y + SIZE . y - PMONITOR - > vecPosition . y , PMONITOR - > vecSize . y - PMONITOR - > vecReservedBottomRight . y , 1 ) ) {
SIZE . y + = PMONITOR - > vecReservedBottomRight . y ;
}
return wlr_box { ( int ) POS . x , ( int ) POS . y , ( int ) SIZE . x , ( int ) SIZE . y } ;
2022-06-27 00:25:37 +02:00
}
void CWindow : : updateWindowDecos ( ) {
for ( auto & wd : m_dWindowDecorations )
wd - > updateWindow ( this ) ;
2022-07-05 17:31:47 +02:00
for ( auto & wd : m_vDecosToRemove ) {
for ( auto it = m_dWindowDecorations . begin ( ) ; it ! = m_dWindowDecorations . end ( ) ; it + + ) {
if ( it - > get ( ) = = wd ) {
it = m_dWindowDecorations . erase ( it ) ;
if ( it = = m_dWindowDecorations . end ( ) )
break ;
}
}
}
m_vDecosToRemove . clear ( ) ;
2022-06-27 13:42:20 +02:00
}
pid_t CWindow : : getPID ( ) {
pid_t PID = - 1 ;
if ( ! m_bIsX11 ) {
2022-09-21 16:10:57 +02:00
wl_client_get_credentials ( wl_resource_get_client ( m_uSurface . xdg - > resource ) , & PID , nullptr , nullptr ) ;
2022-06-27 13:42:20 +02:00
} else {
PID = m_uSurface . xwayland - > pid ;
}
return PID ;
}
2022-07-16 12:44:45 +02:00
IHyprWindowDecoration * CWindow : : getDecorationByType ( eDecorationType type ) {
for ( auto & wd : m_dWindowDecorations ) {
if ( wd - > getDecorationType ( ) = = type )
return wd . get ( ) ;
}
return nullptr ;
2022-08-06 20:57:38 +02:00
}
void CWindow : : createToplevelHandle ( ) {
if ( m_bIsX11 & & ( m_bX11DoesntWantBorders | | m_iX11Type = = 2 ) )
return ; // don't create a toplevel
m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create ( g_pCompositor - > m_sWLRToplevelMgr ) ;
2022-09-25 20:07:48 +02:00
2022-08-06 20:57:38 +02:00
wlr_foreign_toplevel_handle_v1_set_app_id ( m_phForeignToplevel , g_pXWaylandManager - > getAppIDClass ( this ) . c_str ( ) ) ;
wlr_foreign_toplevel_handle_v1_output_enter ( m_phForeignToplevel , g_pCompositor - > getMonitorFromID ( m_iMonitorID ) - > output ) ;
wlr_foreign_toplevel_handle_v1_set_title ( m_phForeignToplevel , m_szTitle . c_str ( ) ) ;
wlr_foreign_toplevel_handle_v1_set_maximized ( m_phForeignToplevel , false ) ;
wlr_foreign_toplevel_handle_v1_set_minimized ( m_phForeignToplevel , false ) ;
wlr_foreign_toplevel_handle_v1_set_fullscreen ( m_phForeignToplevel , false ) ;
// handle events
hyprListener_toplevelActivate . initCallback ( & m_phForeignToplevel - > events . request_activate , [ & ] ( void * owner , void * data ) {
g_pCompositor - > focusWindow ( this ) ;
} , this , " Toplevel " ) ;
hyprListener_toplevelFullscreen . initCallback ( & m_phForeignToplevel - > events . request_fullscreen , [ & ] ( void * owner , void * data ) {
const auto EV = ( wlr_foreign_toplevel_handle_v1_fullscreen_event * ) data ;
g_pCompositor - > setWindowFullscreen ( this , EV - > fullscreen , FULLSCREEN_FULL ) ;
} , this , " Toplevel " ) ;
hyprListener_toplevelClose . initCallback ( & m_phForeignToplevel - > events . request_close , [ & ] ( void * owner , void * data ) {
g_pCompositor - > closeWindow ( this ) ;
} , this , " Toplevel " ) ;
m_iLastToplevelMonitorID = m_iMonitorID ;
}
void CWindow : : destroyToplevelHandle ( ) {
2022-08-06 21:10:37 +02:00
if ( ! m_phForeignToplevel )
return ;
2022-08-06 20:57:38 +02:00
hyprListener_toplevelActivate . removeCallback ( ) ;
hyprListener_toplevelClose . removeCallback ( ) ;
hyprListener_toplevelFullscreen . removeCallback ( ) ;
wlr_foreign_toplevel_handle_v1_destroy ( m_phForeignToplevel ) ;
m_phForeignToplevel = nullptr ;
}
void CWindow : : updateToplevel ( ) {
2022-08-08 21:20:41 +02:00
updateSurfaceOutputs ( ) ;
2022-08-06 21:10:37 +02:00
if ( ! m_phForeignToplevel )
return ;
2022-08-06 20:57:38 +02:00
wlr_foreign_toplevel_handle_v1_set_title ( m_phForeignToplevel , m_szTitle . c_str ( ) ) ;
wlr_foreign_toplevel_handle_v1_set_fullscreen ( m_phForeignToplevel , m_bIsFullscreen ) ;
if ( m_iLastToplevelMonitorID ! = m_iMonitorID ) {
2022-08-10 08:51:59 +02:00
if ( const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iLastToplevelMonitorID ) ; PMONITOR & & PMONITOR - > m_bEnabled )
wlr_foreign_toplevel_handle_v1_output_leave ( m_phForeignToplevel , PMONITOR - > output ) ;
2022-08-06 20:57:38 +02:00
wlr_foreign_toplevel_handle_v1_output_enter ( m_phForeignToplevel , g_pCompositor - > getMonitorFromID ( m_iMonitorID ) - > output ) ;
m_iLastToplevelMonitorID = m_iMonitorID ;
}
2022-08-08 21:20:41 +02:00
}
void sendEnterIter ( wlr_surface * pSurface , int x , int y , void * data ) {
const auto OUTPUT = ( wlr_output * ) data ;
wlr_surface_send_enter ( pSurface , OUTPUT ) ;
}
void sendLeaveIter ( wlr_surface * pSurface , int x , int y , void * data ) {
const auto OUTPUT = ( wlr_output * ) data ;
wlr_surface_send_leave ( pSurface , OUTPUT ) ;
}
void CWindow : : updateSurfaceOutputs ( ) {
2022-08-10 08:51:59 +02:00
if ( m_iLastSurfaceMonitorID = = m_iMonitorID | | ! m_bIsMapped | | m_bHidden | | ! m_bMappedX11 )
2022-08-08 21:20:41 +02:00
return ;
const auto PLASTMONITOR = g_pCompositor - > getMonitorFromID ( m_iLastSurfaceMonitorID ) ;
m_iLastSurfaceMonitorID = m_iMonitorID ;
const auto PNEWMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
2022-08-10 08:51:59 +02:00
if ( PLASTMONITOR & & PLASTMONITOR - > m_bEnabled )
2022-08-08 21:20:41 +02:00
wlr_surface_for_each_surface ( g_pXWaylandManager - > getWindowSurface ( this ) , sendLeaveIter , PLASTMONITOR - > output ) ;
wlr_surface_for_each_surface ( g_pXWaylandManager - > getWindowSurface ( this ) , sendEnterIter , PNEWMONITOR - > output ) ;
2022-08-21 17:01:26 +02:00
}
void CWindow : : moveToWorkspace ( int workspaceID ) {
if ( m_iWorkspaceID ! = workspaceID ) {
m_iWorkspaceID = workspaceID ;
2022-09-21 16:10:57 +02:00
if ( const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( m_iWorkspaceID ) ; PWORKSPACE ) {
2022-08-21 17:01:26 +02:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " movewindow " , getFormat ( " %x,%s " , this , PWORKSPACE - > m_szName . c_str ( ) ) } ) ;
2022-09-21 16:10:57 +02:00
}
2022-08-21 17:01:26 +02:00
}
2022-08-28 19:47:06 +02:00
}
CWindow * CWindow : : X11TransientFor ( ) {
if ( ! m_bIsX11 )
return nullptr ;
if ( ! m_uSurface . xwayland - > parent )
return nullptr ;
auto PPARENT = g_pCompositor - > getWindowFromSurface ( m_uSurface . xwayland - > parent - > surface ) ;
2022-09-01 10:15:55 +02:00
while ( g_pCompositor - > windowValidMapped ( PPARENT ) & & PPARENT - > m_uSurface . xwayland - > parent ) {
2022-08-28 19:47:06 +02:00
PPARENT = g_pCompositor - > getWindowFromSurface ( PPARENT - > m_uSurface . xwayland - > parent - > surface ) ;
}
2022-09-01 10:16:23 +02:00
if ( ! g_pCompositor - > windowValidMapped ( PPARENT ) )
return nullptr ;
2022-08-28 19:47:06 +02:00
return PPARENT ;
}
2022-08-29 19:52:35 +02:00
void CWindow : : removeDecorationByType ( eDecorationType type ) {
for ( auto & wd : m_dWindowDecorations ) {
if ( wd - > getDecorationType ( ) = = type )
m_vDecosToRemove . push_back ( wd . get ( ) ) ;
}
updateWindowDecos ( ) ;
}
2022-10-14 21:46:32 +02:00
2022-11-04 16:56:31 +01:00
void unregisterVar ( void * ptr ) {
( ( CAnimatedVariable * ) ptr ) - > unregister ( ) ;
}
2022-10-14 21:46:32 +02:00
void CWindow : : onUnmap ( ) {
if ( g_pCompositor - > m_pLastWindow = = this )
g_pCompositor - > m_pLastWindow = nullptr ;
2022-11-04 16:56:31 +01:00
m_vRealPosition . setCallbackOnEnd ( unregisterVar ) ;
m_vRealSize . setCallbackOnEnd ( unregisterVar ) ;
m_cRealBorderColor . setCallbackOnEnd ( unregisterVar ) ;
m_fActiveInactiveAlpha . setCallbackOnEnd ( unregisterVar ) ;
m_fAlpha . setCallbackOnEnd ( unregisterVar ) ;
m_cRealShadowColor . setCallbackOnEnd ( unregisterVar ) ;
m_fDimPercent . setCallbackOnEnd ( unregisterVar ) ;
2022-11-06 18:52:09 +01:00
m_vRealSize . setCallbackOnBegin ( nullptr ) ;
2022-11-04 16:56:31 +01:00
}
void CWindow : : onMap ( ) {
m_vRealPosition . registerVar ( ) ;
m_vRealSize . registerVar ( ) ;
m_cRealBorderColor . registerVar ( ) ;
m_fActiveInactiveAlpha . registerVar ( ) ;
m_fAlpha . registerVar ( ) ;
m_cRealShadowColor . registerVar ( ) ;
m_fDimPercent . registerVar ( ) ;
2022-11-06 18:52:09 +01:00
m_vRealSize . setCallbackOnEnd ( [ & ] ( void * ptr ) {
g_pHyprOpenGL - > onWindowResizeEnd ( this ) ;
} , false ) ;
m_vRealSize . setCallbackOnBegin ( [ & ] ( void * ptr ) {
g_pHyprOpenGL - > onWindowResizeStart ( this ) ;
} , false ) ;
2022-10-14 21:46:32 +02:00
}
void CWindow : : setHidden ( bool hidden ) {
m_bHidden = hidden ;
2022-11-05 14:37:57 +01:00
if ( hidden & & g_pCompositor - > m_pLastWindow = = this ) {
g_pCompositor - > m_pLastWindow = nullptr ;
2022-10-14 21:46:32 +02:00
}
}
bool CWindow : : isHidden ( ) {
return m_bHidden ;
2022-11-15 11:21:26 +01:00
}
void CWindow : : applyDynamicRule ( const SWindowRule & r ) {
if ( r . szRule = = " noblur " ) {
m_sAdditionalConfigData . forceNoBlur = true ;
} else if ( r . szRule = = " noborder " ) {
m_sAdditionalConfigData . forceNoBorder = true ;
} else if ( r . szRule = = " noshadow " ) {
m_sAdditionalConfigData . forceNoShadow = true ;
} else if ( r . szRule = = " opaque " ) {
m_sAdditionalConfigData . forceOpaque = true ;
} else if ( r . szRule . find ( " rounding " ) = = 0 ) {
try {
m_sAdditionalConfigData . rounding = std : : stoi ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
} catch ( std : : exception & e ) {
Debug : : log ( ERR , " Rounding rule \" %s \" failed with: %s " , r . szRule . c_str ( ) , e . what ( ) ) ;
}
} else if ( r . szRule . find ( " opacity " ) = = 0 ) {
try {
std : : string alphaPart = removeBeginEndSpacesTabs ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
if ( alphaPart . contains ( ' ' ) ) {
// we have a space, 2 values
m_sSpecialRenderData . alpha = std : : stof ( alphaPart . substr ( 0 , alphaPart . find_first_of ( ' ' ) ) ) ;
m_sSpecialRenderData . alphaInactive = std : : stof ( alphaPart . substr ( alphaPart . find_first_of ( ' ' ) + 1 ) ) ;
} else {
m_sSpecialRenderData . alpha = std : : stof ( alphaPart ) ;
}
} catch ( std : : exception & e ) {
Debug : : log ( ERR , " Opacity rule \" %s \" failed with: %s " , r . szRule . c_str ( ) , e . what ( ) ) ;
}
} else if ( r . szRule = = " noanim " ) {
m_sAdditionalConfigData . forceNoAnims = true ;
} else if ( r . szRule . find ( " animation " ) = = 0 ) {
auto STYLE = r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ;
m_sAdditionalConfigData . animationStyle = STYLE ;
} else if ( r . szRule . find ( " bordercolor " ) = = 0 ) {
try {
std : : string colorPart = removeBeginEndSpacesTabs ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
if ( colorPart . contains ( ' ' ) ) {
// we have a space, 2 values
m_sSpecialRenderData . activeBorderColor = configStringToInt ( colorPart . substr ( 0 , colorPart . find_first_of ( ' ' ) ) ) ;
m_sSpecialRenderData . inactiveBorderColor = configStringToInt ( colorPart . substr ( colorPart . find_first_of ( ' ' ) + 1 ) ) ;
} else {
m_sSpecialRenderData . activeBorderColor = configStringToInt ( colorPart ) ;
}
} catch ( std : : exception & e ) {
Debug : : log ( ERR , " BorderColor rule \" %s \" failed with: %s " , r . szRule . c_str ( ) , e . what ( ) ) ;
}
}
}
void CWindow : : updateDynamicRules ( ) {
m_sSpecialRenderData . activeBorderColor = - 1 ;
m_sSpecialRenderData . inactiveBorderColor = - 1 ;
m_sSpecialRenderData . alpha = 1.f ;
m_sSpecialRenderData . alphaInactive = - 1.f ;
m_sAdditionalConfigData . forceNoBlur = false ;
m_sAdditionalConfigData . forceNoBorder = false ;
m_sAdditionalConfigData . forceNoShadow = false ;
m_sAdditionalConfigData . forceOpaque = false ;
m_sAdditionalConfigData . forceNoAnims = false ;
m_sAdditionalConfigData . animationStyle = " " ;
m_sAdditionalConfigData . rounding = - 1 ;
const auto WINDOWRULES = g_pConfigManager - > getMatchingRules ( this ) ;
for ( auto & r : WINDOWRULES ) {
applyDynamicRule ( r ) ;
}
}