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"
2023-09-20 17:25:03 +02:00
# include "render/decorations/CHyprGroupBarDecoration.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 ) ;
2023-02-01 22:06:01 +01:00
m_fBorderFadeAnimationProgress . create ( AVARTYPE_FLOAT , g_pConfigManager - > getAnimationPropertyConfig ( " border " ) , ( void * ) this , AVARDAMAGE_BORDER ) ;
m_fBorderAngleAnimationProgress . create ( AVARTYPE_FLOAT , g_pConfigManager - > getAnimationPropertyConfig ( " borderangle " ) , ( void * ) this , AVARDAMAGE_BORDER ) ;
2022-07-28 13:28:43 +02:00
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-12-16 18:17:31 +01: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
}
2023-08-09 14:28:04 +02:00
SWindowDecorationExtents CWindow : : getFullWindowExtents ( ) {
if ( m_bFadingOut )
return m_eOriginalClosedExtents ;
2023-08-17 10:13:19 +02:00
const int BORDERSIZE = getRealBorderSize ( ) ;
2023-07-23 15:49:49 +02:00
2022-12-31 19:23:02 +01:00
if ( m_sAdditionalConfigData . dimAround ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
2023-08-09 14:28:04 +02:00
return { { m_vRealPosition . vec ( ) . x - PMONITOR - > vecPosition . x , m_vRealPosition . vec ( ) . y - PMONITOR - > vecPosition . y } ,
{ PMONITOR - > vecSize . x - ( m_vRealPosition . vec ( ) . x - PMONITOR - > vecPosition . x ) , PMONITOR - > vecSize . y - ( m_vRealPosition . vec ( ) . y - PMONITOR - > vecPosition . y ) } } ;
2022-12-31 19:23:02 +01:00
}
2022-05-30 14:55:42 +02:00
2023-08-17 10:13:19 +02:00
SWindowDecorationExtents maxExtents = { { BORDERSIZE + 2 , BORDERSIZE + 2 } , { BORDERSIZE + 2 , BORDERSIZE + 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 ;
}
2023-06-23 13:54:01 +02:00
if ( m_pWLSurface . exists ( ) & & ! m_bIsX11 ) {
wlr_box surfaceExtents = { 0 , 0 , 0 , 0 } ;
// TODO: this could be better, perhaps make a getFullWindowRegion?
wlr_xdg_surface_for_each_popup_surface (
m_uSurface . xdg ,
[ ] ( wlr_surface * surf , int sx , int sy , void * data ) {
wlr_box * pSurfaceExtents = ( wlr_box * ) data ;
if ( sx < pSurfaceExtents - > x )
pSurfaceExtents - > x = sx ;
if ( sy < pSurfaceExtents - > y )
pSurfaceExtents - > y = sy ;
if ( sx + surf - > current . width > pSurfaceExtents - > width )
pSurfaceExtents - > width = sx + surf - > current . width - pSurfaceExtents - > x ;
if ( sy + surf - > current . height > pSurfaceExtents - > height )
pSurfaceExtents - > height = sy + surf - > current . height - pSurfaceExtents - > y ;
} ,
& surfaceExtents ) ;
if ( - surfaceExtents . x > maxExtents . topLeft . x )
maxExtents . topLeft . x = - surfaceExtents . x ;
if ( - surfaceExtents . y > maxExtents . topLeft . y )
maxExtents . topLeft . y = - surfaceExtents . y ;
if ( surfaceExtents . x + surfaceExtents . width > m_pWLSurface . wlr ( ) - > current . width + maxExtents . bottomRight . x )
maxExtents . bottomRight . x = surfaceExtents . x + surfaceExtents . width - m_pWLSurface . wlr ( ) - > current . width ;
if ( surfaceExtents . y + surfaceExtents . height > m_pWLSurface . wlr ( ) - > current . height + maxExtents . bottomRight . y )
maxExtents . bottomRight . y = surfaceExtents . y + surfaceExtents . height - m_pWLSurface . wlr ( ) - > current . height ;
}
2023-08-09 14:28:04 +02:00
return maxExtents ;
}
wlr_box CWindow : : getFullWindowBoundingBox ( ) {
if ( m_sAdditionalConfigData . dimAround ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
return { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
}
auto maxExtents = getFullWindowExtents ( ) ;
2022-12-16 18:17:31 +01:00
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 ) ;
2022-12-16 18:17:31 +01:00
auto POS = m_vPosition ;
auto SIZE = m_vSize ;
2022-06-23 20:39:48 +02:00
2022-11-22 00:33:23 +01:00
if ( m_bIsFullscreen ) {
2022-12-16 18:17:31 +01:00
POS = PMONITOR - > vecPosition ;
2022-11-22 00:33:23 +01:00
SIZE = PMONITOR - > vecSize ;
return wlr_box { ( int ) POS . x , ( int ) POS . y , ( int ) SIZE . x , ( int ) SIZE . y } ;
}
2022-06-23 20:39:48 +02:00
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
}
2023-02-28 23:32:42 +01:00
wlr_box CWindow : : getWindowInputBox ( ) {
2023-08-17 10:13:19 +02:00
const int BORDERSIZE = getRealBorderSize ( ) ;
2023-02-28 23:32:42 +01:00
if ( m_sAdditionalConfigData . dimAround ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
return { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
}
2023-08-17 10:13:19 +02:00
SWindowDecorationExtents maxExtents = { { BORDERSIZE + 2 , BORDERSIZE + 2 } , { BORDERSIZE + 2 , BORDERSIZE + 2 } } ;
2023-02-28 23:32:42 +01:00
for ( auto & wd : m_dWindowDecorations ) {
if ( ! wd - > allowsInput ( ) )
continue ;
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 } ;
return finalBox ;
}
2023-10-29 19:09:05 +01:00
wlr_box CWindow : : getWindowMainSurfaceBox ( ) {
return { m_vRealPosition . vec ( ) . x , m_vRealPosition . vec ( ) . y , m_vRealSize . vec ( ) . x , m_vRealSize . vec ( ) . y } ;
}
2023-02-28 20:36:36 +01:00
SWindowDecorationExtents CWindow : : getFullWindowReservedArea ( ) {
SWindowDecorationExtents extents ;
for ( auto & wd : m_dWindowDecorations ) {
const auto RESERVED = wd - > getWindowDecorationReservedArea ( ) ;
if ( RESERVED . bottomRight = = Vector2D { } & & RESERVED . topLeft = = Vector2D { } )
continue ;
extents . topLeft = extents . topLeft + RESERVED . topLeft ;
extents . bottomRight = extents . bottomRight + RESERVED . bottomRight ;
}
return extents ;
}
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
2023-06-05 09:49:17 +02:00
bool recalc = false ;
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 ) {
2023-06-05 09:49:17 +02:00
it = m_dWindowDecorations . erase ( it ) ;
recalc = true ;
2022-07-05 17:31:47 +02:00
if ( it = = m_dWindowDecorations . end ( ) )
break ;
}
}
}
2023-06-05 09:49:17 +02:00
if ( recalc )
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateWindow ( this ) ;
2022-07-05 17:31:47 +02:00
m_vDecosToRemove . clear ( ) ;
2022-06-27 13:42:20 +02:00
}
pid_t CWindow : : getPID ( ) {
pid_t PID = - 1 ;
if ( ! m_bIsX11 ) {
2023-03-03 12:17:43 +01:00
if ( ! m_bIsMapped )
return - 1 ;
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 {
2023-11-01 19:53:36 +01:00
if ( ! m_bIsMapped | | ! m_bMappedX11 )
return - 1 ;
2022-06-27 13:42:20 +02:00
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
2022-12-16 18:17:31 +01:00
hyprListener_toplevelActivate . initCallback (
2023-07-19 12:39:45 +02:00
& m_phForeignToplevel - > events . request_activate , [ & ] ( void * owner , void * data ) { g_pLayoutManager - > getCurrentLayout ( ) - > requestFocusForWindow ( this ) ; } , this , " Toplevel " ) ;
2022-12-16 18:17:31 +01:00
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 (
2022-12-20 03:18:47 +01:00
& m_phForeignToplevel - > events . request_close , [ & ] ( void * owner , void * data ) { g_pCompositor - > closeWindow ( this ) ; } , this , " Toplevel " ) ;
2022-08-06 20:57:38 +02:00
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 )
2023-03-20 16:00:58 +01:00
wlr_surface_for_each_surface ( m_pWLSurface . wlr ( ) , sendLeaveIter , PLASTMONITOR - > output ) ;
2022-08-08 21:20:41 +02:00
2023-03-20 16:00:58 +01:00
wlr_surface_for_each_surface ( m_pWLSurface . wlr ( ) , sendEnterIter , PNEWMONITOR - > output ) ;
2023-06-06 09:48:07 +02:00
wlr_surface_for_each_surface (
m_pWLSurface . wlr ( ) ,
[ ] ( wlr_surface * surf , int x , int y , void * data ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( ( ( CWindow * ) data ) - > m_iMonitorID ) ;
2023-10-22 17:58:06 +02:00
g_pCompositor - > setPreferredScaleForSurface ( surf , PMONITOR ? PMONITOR - > scale : 1.f ) ;
g_pCompositor - > setPreferredTransformForSurface ( surf , PMONITOR - > transform ) ;
2023-06-06 09:48:07 +02:00
} ,
this ) ;
2022-08-21 17:01:26 +02:00
}
void CWindow : : moveToWorkspace ( int workspaceID ) {
2023-03-18 17:30:29 +01:00
if ( m_iWorkspaceID = = workspaceID )
return ;
2022-08-21 17:01:26 +02:00
2023-10-24 01:58:44 +02:00
static auto * const PCLOSEONLASTSPECIAL = & g_pConfigManager - > getConfigValuePtr ( " misc:close_special_on_empty " ) - > intValue ;
const int OLDWORKSPACE = m_iWorkspaceID ;
2023-03-18 17:30:29 +01:00
m_iWorkspaceID = workspaceID ;
2023-01-20 19:44:30 +01:00
2023-03-18 17:30:29 +01:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( m_iWorkspaceID ) ;
2023-08-17 10:13:19 +02:00
updateSpecialRenderData ( ) ;
2023-03-18 17:30:29 +01:00
if ( PWORKSPACE ) {
2023-09-20 09:26:20 +02:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " movewindow " , std : : format ( " {:x},{} " , ( uintptr_t ) this , PWORKSPACE - > m_szName ) } ) ;
2023-03-18 17:30:29 +01:00
EMIT_HOOK_EVENT ( " moveWindow " , ( std : : vector < void * > { this , PWORKSPACE } ) ) ;
2022-08-21 17:01:26 +02:00
}
2023-03-18 17:30:29 +01:00
2023-04-02 11:24:17 +02:00
if ( m_pSwallowed ) {
m_pSwallowed - > moveToWorkspace ( workspaceID ) ;
m_pSwallowed - > m_iMonitorID = m_iMonitorID ;
}
2023-08-15 19:15:37 +02:00
// update xwayland coords
g_pXWaylandManager - > setWindowSize ( this , m_vRealSize . vec ( ) ) ;
2023-10-24 01:58:44 +02:00
if ( g_pCompositor - > isWorkspaceSpecial ( OLDWORKSPACE ) & & g_pCompositor - > getWindowsOnWorkspace ( OLDWORKSPACE ) = = 0 & & * PCLOSEONLASTSPECIAL ) {
const auto PWS = g_pCompositor - > getWorkspaceByID ( OLDWORKSPACE ) ;
if ( PWS ) {
if ( const auto PMONITOR = g_pCompositor - > getMonitorFromID ( PWS - > m_iMonitorID ) ; PMONITOR )
PMONITOR - > setSpecialWorkspace ( nullptr ) ;
}
}
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 ( ) {
2023-09-03 13:00:02 +02:00
static auto * const PCLOSEONLASTSPECIAL = & g_pConfigManager - > getConfigValuePtr ( " misc:close_special_on_empty " ) - > intValue ;
2022-10-14 21:46:32 +02:00
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 ) ;
2023-02-01 22:06:01 +01:00
m_fBorderFadeAnimationProgress . setCallbackOnEnd ( unregisterVar ) ;
m_fBorderAngleAnimationProgress . setCallbackOnEnd ( unregisterVar ) ;
2022-11-04 16:56:31 +01:00
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 ) ;
2023-01-20 19:15:15 +01:00
std : : erase_if ( g_pCompositor - > m_vWindowFocusHistory , [ & ] ( const auto & other ) { return other = = this ; } ) ;
2023-03-23 01:39:32 +01:00
m_pWLSurface . unassign ( ) ;
2023-03-28 21:17:47 +02:00
hyprListener_unmapWindow . removeCallback ( ) ;
2023-09-03 13:00:02 +02:00
if ( * PCLOSEONLASTSPECIAL & & g_pCompositor - > getWindowsOnWorkspace ( m_iWorkspaceID ) = = 0 & & g_pCompositor - > isWorkspaceSpecial ( m_iWorkspaceID ) ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
2023-09-03 13:02:05 +02:00
if ( PMONITOR & & PMONITOR - > specialWorkspaceID = = m_iWorkspaceID )
2023-09-03 13:00:02 +02:00
PMONITOR - > setSpecialWorkspace ( nullptr ) ;
}
2023-09-28 22:48:33 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( m_iMonitorID ) ;
if ( PMONITOR & & PMONITOR - > solitaryClient = = this )
PMONITOR - > solitaryClient = nullptr ;
2022-11-04 16:56:31 +01:00
}
void CWindow : : onMap ( ) {
2022-11-18 14:53:54 +01:00
2023-03-20 16:00:58 +01:00
m_pWLSurface . assign ( g_pXWaylandManager - > getWindowSurface ( this ) ) ;
2023-10-20 21:15:41 +02:00
m_pWLSurface . m_pOwner = this ;
2023-03-20 16:00:58 +01:00
2022-11-18 14:53:54 +01:00
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
m_vRealPosition . resetAllCallbacks ( ) ;
m_vRealSize . resetAllCallbacks ( ) ;
2023-02-01 22:06:01 +01:00
m_fBorderFadeAnimationProgress . resetAllCallbacks ( ) ;
m_fBorderAngleAnimationProgress . resetAllCallbacks ( ) ;
2022-11-18 14:53:54 +01:00
m_fActiveInactiveAlpha . resetAllCallbacks ( ) ;
m_fAlpha . resetAllCallbacks ( ) ;
m_cRealShadowColor . resetAllCallbacks ( ) ;
m_fDimPercent . resetAllCallbacks ( ) ;
2022-11-04 16:56:31 +01:00
m_vRealPosition . registerVar ( ) ;
m_vRealSize . registerVar ( ) ;
2023-02-01 22:06:01 +01:00
m_fBorderFadeAnimationProgress . registerVar ( ) ;
m_fBorderAngleAnimationProgress . registerVar ( ) ;
2022-11-04 16:56:31 +01:00
m_fActiveInactiveAlpha . registerVar ( ) ;
m_fAlpha . registerVar ( ) ;
m_cRealShadowColor . registerVar ( ) ;
m_fDimPercent . registerVar ( ) ;
2022-11-06 18:52:09 +01:00
2023-02-01 22:06:01 +01:00
m_fBorderAngleAnimationProgress . setCallbackOnEnd ( [ & ] ( void * ptr ) { onBorderAngleAnimEnd ( ptr ) ; } , false ) ;
m_fBorderAngleAnimationProgress . setValueAndWarp ( 0.f ) ;
m_fBorderAngleAnimationProgress = 1.f ;
2023-01-20 19:15:15 +01:00
g_pCompositor - > m_vWindowFocusHistory . push_back ( this ) ;
2023-03-28 21:17:47 +02:00
2023-06-03 12:20:23 +02:00
hyprListener_unmapWindow . initCallback ( m_bIsX11 ? & m_uSurface . xwayland - > surface - > events . unmap : & m_uSurface . xdg - > surface - > events . unmap , & Events : : listener_unmapWindow , this ,
" CWindow " ) ;
2023-10-20 21:15:41 +02:00
m_vReportedSize = m_vPendingReportedSize ;
2022-10-14 21:46:32 +02:00
}
2023-02-01 22:06:01 +01:00
void CWindow : : onBorderAngleAnimEnd ( void * ptr ) {
const auto PANIMVAR = ( CAnimatedVariable * ) ptr ;
const std : : string STYLE = PANIMVAR - > getConfig ( ) - > pValues - > internalStyle ;
2023-02-14 18:10:17 +01:00
if ( STYLE ! = " loop " | | ! PANIMVAR - > getConfig ( ) - > pValues - > internalEnabled )
2023-02-01 22:06:01 +01:00
return ;
PANIMVAR - > setCallbackOnEnd ( nullptr ) ; // we remove the callback here because otherwise setvalueandwarp will recurse this
PANIMVAR - > setValueAndWarp ( 0 ) ;
* PANIMVAR = 1.f ;
PANIMVAR - > setCallbackOnEnd ( [ & ] ( void * ptr ) { onBorderAngleAnimEnd ( ptr ) ; } , 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 ;
2023-05-31 21:11:20 +02:00
} else if ( r . szRule = = " nodim " ) {
m_sAdditionalConfigData . forceNoDim = true ;
2023-03-26 03:00:24 +02:00
} else if ( r . szRule = = " forcergbx " ) {
m_sAdditionalConfigData . forceRGBX = true ;
2022-11-15 11:21:26 +01:00
} else if ( r . szRule = = " opaque " ) {
2023-03-30 00:44:25 +02:00
if ( ! m_sAdditionalConfigData . forceOpaqueOverridden )
2022-11-23 10:55:46 +01:00
m_sAdditionalConfigData . forceOpaque = true ;
2023-09-28 22:48:33 +02:00
} else if ( r . szRule = = " immediate " ) {
m_sAdditionalConfigData . forceTearing = true ;
2023-10-24 22:28:55 +02:00
} else if ( r . szRule = = " nearestneighbor " ) {
m_sAdditionalConfigData . nearestNeighbor = true ;
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " rounding " ) ) {
2022-11-15 11:21:26 +01:00
try {
m_sAdditionalConfigData . rounding = std : : stoi ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
2023-09-06 21:45:37 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rounding rule \" {} \" failed with: {} " , r . szRule , e . what ( ) ) ; }
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " bordersize " ) ) {
2023-07-18 00:11:29 +02:00
try {
m_sAdditionalConfigData . borderSize = std : : stoi ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
2023-09-06 21:45:37 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Bordersize rule \" {} \" failed with: {} " , r . szRule , e . what ( ) ) ; }
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " opacity " ) ) {
2022-11-15 11:21:26 +01:00
try {
2022-12-11 18:15:02 +01:00
CVarList vars ( r . szRule , 0 , ' ' ) ;
2023-07-21 19:05:00 +02:00
int opacityIDX = 0 ;
for ( auto & r : vars ) {
if ( r = = " opacity " )
continue ;
if ( r = = " override " ) {
2023-07-23 16:03:59 +02:00
if ( opacityIDX = = 1 ) {
2023-07-21 19:05:00 +02:00
m_sSpecialRenderData . alphaOverride = true ;
m_sSpecialRenderData . alphaInactiveOverride = true ;
2023-07-23 16:03:59 +02:00
} else if ( opacityIDX = = 2 )
2023-07-21 19:05:00 +02:00
m_sSpecialRenderData . alphaInactiveOverride = true ;
2022-12-11 18:15:02 +01:00
} else {
2023-07-21 19:05:00 +02:00
if ( opacityIDX = = 0 ) {
m_sSpecialRenderData . alpha = std : : stof ( r ) ;
m_sSpecialRenderData . alphaInactive = std : : stof ( r ) ;
} else if ( opacityIDX = = 1 ) {
m_sSpecialRenderData . alphaInactive = std : : stof ( r ) ;
m_sSpecialRenderData . alphaInactiveOverride = false ;
2022-12-11 18:15:02 +01:00
} else {
2023-07-21 19:05:00 +02:00
throw std : : runtime_error ( " more than 2 alpha values " ) ;
2022-12-11 18:15:02 +01:00
}
2023-07-21 19:05:00 +02:00
opacityIDX + + ;
2022-12-11 18:15:02 +01:00
}
2022-11-15 11:21:26 +01:00
}
2023-09-06 21:45:37 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Opacity rule \" {} \" failed with: {} " , r . szRule , e . what ( ) ) ; }
2022-12-16 18:17:31 +01:00
} else if ( r . szRule = = " noanim " ) {
m_sAdditionalConfigData . forceNoAnims = true ;
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " animation " ) ) {
2022-12-16 18:17:31 +01:00
auto STYLE = r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ;
m_sAdditionalConfigData . animationStyle = STYLE ;
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " bordercolor " ) ) {
2022-11-15 11:21:26 +01:00
try {
std : : string colorPart = removeBeginEndSpacesTabs ( r . szRule . substr ( r . szRule . find_first_of ( ' ' ) + 1 ) ) ;
if ( colorPart . contains ( ' ' ) ) {
// we have a space, 2 values
2022-12-16 18:17:31 +01:00
m_sSpecialRenderData . activeBorderColor = configStringToInt ( colorPart . substr ( 0 , colorPart . find_first_of ( ' ' ) ) ) ;
2022-11-15 11:21:26 +01:00
m_sSpecialRenderData . inactiveBorderColor = configStringToInt ( colorPart . substr ( colorPart . find_first_of ( ' ' ) + 1 ) ) ;
} else {
m_sSpecialRenderData . activeBorderColor = configStringToInt ( colorPart ) ;
}
2023-09-06 21:45:37 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " BorderColor rule \" {} \" failed with: {} " , r . szRule , e . what ( ) ) ; }
2022-12-28 15:39:17 +01:00
} else if ( r . szRule = = " dimaround " ) {
m_sAdditionalConfigData . dimAround = true ;
2023-08-08 18:52:20 +02:00
} else if ( r . szRule = = " keepaspectratio " ) {
m_sAdditionalConfigData . keepAspectRatio = true ;
2023-10-15 20:07:23 +02:00
} else if ( r . szRule . starts_with ( " xray " ) ) {
2023-08-09 22:03:24 +02:00
CVarList vars ( r . szRule , 0 , ' ' ) ;
try {
m_sAdditionalConfigData . xray = configStringToInt ( vars [ 1 ] ) ;
} catch ( . . . ) { }
2022-11-15 11:21:26 +01:00
}
}
void CWindow : : updateDynamicRules ( ) {
2022-12-16 18:17:31 +01:00
m_sSpecialRenderData . activeBorderColor = - 1 ;
2022-11-15 11:21:26 +01:00
m_sSpecialRenderData . inactiveBorderColor = - 1 ;
2022-12-16 18:17:31 +01:00
m_sSpecialRenderData . alpha = 1.f ;
m_sSpecialRenderData . alphaInactive = - 1.f ;
m_sAdditionalConfigData . forceNoBlur = false ;
m_sAdditionalConfigData . forceNoBorder = false ;
m_sAdditionalConfigData . forceNoShadow = false ;
2023-05-31 21:11:20 +02:00
m_sAdditionalConfigData . forceNoDim = false ;
2023-03-30 00:44:25 +02:00
if ( ! m_sAdditionalConfigData . forceOpaqueOverridden )
2022-11-23 10:55:46 +01:00
m_sAdditionalConfigData . forceOpaque = false ;
2023-08-08 18:52:20 +02:00
m_sAdditionalConfigData . forceNoAnims = false ;
m_sAdditionalConfigData . animationStyle = std : : string ( " " ) ;
m_sAdditionalConfigData . rounding = - 1 ;
m_sAdditionalConfigData . dimAround = false ;
m_sAdditionalConfigData . forceRGBX = false ;
m_sAdditionalConfigData . borderSize = - 1 ;
m_sAdditionalConfigData . keepAspectRatio = false ;
2023-08-09 22:03:24 +02:00
m_sAdditionalConfigData . xray = - 1 ;
2023-09-28 22:48:33 +02:00
m_sAdditionalConfigData . forceTearing = false ;
2023-10-24 22:28:55 +02:00
m_sAdditionalConfigData . nearestNeighbor = false ;
2022-11-15 11:21:26 +01:00
const auto WINDOWRULES = g_pConfigManager - > getMatchingRules ( this ) ;
for ( auto & r : WINDOWRULES ) {
applyDynamicRule ( r ) ;
}
2023-07-18 00:11:43 +02:00
2023-07-18 11:49:57 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m_iMonitorID ) ;
2022-11-15 11:21:26 +01:00
}
2023-02-18 23:35:31 +01:00
// check if the point is "hidden" under a rounded corner of the window
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// otherwise behaviour is undefined
bool CWindow : : isInCurvedCorner ( double x , double y ) {
2023-08-17 10:13:19 +02:00
const int ROUNDING = rounding ( ) ;
if ( getRealBorderSize ( ) > = ROUNDING )
2023-02-18 23:35:31 +01:00
return false ;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
2023-08-17 10:13:19 +02:00
double x0 = m_vRealPosition . vec ( ) . x + ROUNDING ;
double y0 = m_vRealPosition . vec ( ) . y + ROUNDING ;
double x1 = m_vRealPosition . vec ( ) . x + m_vRealSize . vec ( ) . x - ROUNDING ;
double y1 = m_vRealPosition . vec ( ) . y + m_vRealSize . vec ( ) . y - ROUNDING ;
2023-02-18 23:35:31 +01:00
if ( x < x0 & & y < y0 ) {
2023-08-17 10:13:19 +02:00
return Vector2D { x0 , y0 } . distance ( Vector2D { x , y } ) > ( double ) ROUNDING ;
2023-02-18 23:35:31 +01:00
}
if ( x > x1 & & y < y0 ) {
2023-08-17 10:13:19 +02:00
return Vector2D { x1 , y0 } . distance ( Vector2D { x , y } ) > ( double ) ROUNDING ;
2023-02-18 23:35:31 +01:00
}
if ( x < x0 & & y > y1 ) {
2023-08-17 10:13:19 +02:00
return Vector2D { x0 , y1 } . distance ( Vector2D { x , y } ) > ( double ) ROUNDING ;
2023-02-18 23:35:31 +01:00
}
if ( x > x1 & & y > y1 ) {
2023-08-17 10:13:19 +02:00
return Vector2D { x1 , y1 } . distance ( Vector2D { x , y } ) > ( double ) ROUNDING ;
2023-02-18 23:35:31 +01:00
}
return false ;
}
void findExtensionForVector2D ( wlr_surface * surface , int x , int y , void * data ) {
const auto DATA = ( SExtensionFindingData * ) data ;
wlr_box box = { DATA - > origin . x + x , DATA - > origin . y + y , surface - > current . width , surface - > current . height } ;
if ( wlr_box_contains_point ( & box , DATA - > vec . x , DATA - > vec . y ) )
* DATA - > found = surface ;
}
// checks if the wayland window has a popup at pos
bool CWindow : : hasPopupAt ( const Vector2D & pos ) {
if ( m_bIsX11 )
return false ;
wlr_surface * resultSurf = nullptr ;
Vector2D origin = m_vRealPosition . vec ( ) ;
SExtensionFindingData data = { origin , pos , & resultSurf } ;
wlr_xdg_surface_for_each_popup_surface ( m_uSurface . xdg , findExtensionForVector2D , & data ) ;
return resultSurf ;
}
2023-02-19 22:07:32 +01:00
2023-09-22 01:42:00 +02:00
void CWindow : : applyGroupRules ( ) {
if ( ( m_eGroupRules & GROUP_SET & & m_bFirstMap ) | | m_eGroupRules & GROUP_SET_ALWAYS )
createGroup ( ) ;
if ( m_sGroupData . pNextWindow & & ( ( m_eGroupRules & GROUP_LOCK & & m_bFirstMap ) | | m_eGroupRules & GROUP_LOCK_ALWAYS ) )
getGroupHead ( ) - > m_sGroupData . locked = true ;
}
void CWindow : : createGroup ( ) {
if ( m_sGroupData . deny ) {
Debug : : log ( LOG , " createGroup: window:{:x},title:{} is denied as a group, ignored " , ( uintptr_t ) this , this - > m_szTitle ) ;
return ;
}
if ( ! m_sGroupData . pNextWindow ) {
m_sGroupData . pNextWindow = this ;
m_sGroupData . head = true ;
m_sGroupData . locked = false ;
m_sGroupData . deny = false ;
m_dWindowDecorations . emplace_back ( std : : make_unique < CHyprGroupBarDecoration > ( this ) ) ;
updateWindowDecos ( ) ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateWindow ( this ) ;
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
}
}
void CWindow : : destroyGroup ( ) {
if ( m_sGroupData . pNextWindow = = this ) {
if ( m_eGroupRules & GROUP_SET_ALWAYS ) {
Debug : : log ( LOG , " destoryGroup: window:{:x},title:{} has rule [group set always], ignored " , ( uintptr_t ) this , this - > m_szTitle ) ;
return ;
}
m_sGroupData . pNextWindow = nullptr ;
updateWindowDecos ( ) ;
return ;
}
CWindow * curr = this ;
std : : vector < CWindow * > members ;
do {
const auto PLASTWIN = curr ;
curr = curr - > m_sGroupData . pNextWindow ;
PLASTWIN - > m_sGroupData . pNextWindow = nullptr ;
curr - > setHidden ( false ) ;
members . push_back ( curr ) ;
} while ( curr ! = this ) ;
for ( auto & w : members ) {
if ( w - > m_sGroupData . head )
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowRemoved ( curr ) ;
w - > m_sGroupData . head = false ;
}
const bool GROUPSLOCKEDPREV = g_pKeybindManager - > m_bGroupsLocked ;
g_pKeybindManager - > m_bGroupsLocked = true ;
for ( auto & w : members ) {
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreated ( w ) ;
w - > updateWindowDecos ( ) ;
}
g_pKeybindManager - > m_bGroupsLocked = GROUPSLOCKEDPREV ;
}
2023-02-19 22:07:32 +01:00
CWindow * CWindow : : getGroupHead ( ) {
CWindow * curr = this ;
while ( ! curr - > m_sGroupData . head )
curr = curr - > m_sGroupData . pNextWindow ;
return curr ;
}
CWindow * CWindow : : getGroupTail ( ) {
CWindow * curr = this ;
while ( ! curr - > m_sGroupData . pNextWindow - > m_sGroupData . head )
curr = curr - > m_sGroupData . pNextWindow ;
return curr ;
}
CWindow * CWindow : : getGroupCurrent ( ) {
CWindow * curr = this ;
while ( curr - > isHidden ( ) )
curr = curr - > m_sGroupData . pNextWindow ;
return curr ;
}
2023-08-30 17:39:22 +02:00
int CWindow : : getGroupSize ( ) {
int size = 1 ;
CWindow * curr = this ;
while ( curr - > m_sGroupData . pNextWindow ! = this ) {
curr = curr - > m_sGroupData . pNextWindow ;
size + + ;
}
return size ;
}
2023-10-30 15:54:12 +01:00
bool CWindow : : canBeGroupedInto ( CWindow * pWindow ) {
return ! g_pKeybindManager - > m_bGroupsLocked // global group lock disengaged
& & ( ( m_eGroupRules & GROUP_INVADE & & m_bFirstMap ) // window ignore local group locks, or
| | ( ! pWindow - > getGroupHead ( ) - > m_sGroupData . locked // target unlocked
& & ! ( m_sGroupData . pNextWindow & & getGroupHead ( ) - > m_sGroupData . locked ) ) ) // source unlocked or isn't group
& & ! m_sGroupData . deny // source is not denied entry
& & ! ( m_eGroupRules & GROUP_BARRED & & m_bFirstMap ) ; // group rule doesn't prevent adding window
}
2023-08-30 17:39:22 +02:00
CWindow * CWindow : : getGroupWindowByIndex ( int index ) {
const int SIZE = getGroupSize ( ) ;
index = ( ( index % SIZE ) + SIZE ) % SIZE ;
CWindow * curr = getGroupHead ( ) ;
while ( index > 0 ) {
curr = curr - > m_sGroupData . pNextWindow ;
index - - ;
}
return curr ;
}
2023-02-19 22:07:32 +01:00
void CWindow : : setGroupCurrent ( CWindow * pWindow ) {
CWindow * curr = this - > m_sGroupData . pNextWindow ;
bool isMember = false ;
while ( curr ! = this ) {
if ( curr = = pWindow ) {
isMember = true ;
break ;
}
curr = curr - > m_sGroupData . pNextWindow ;
}
if ( ! isMember & & pWindow ! = this )
return ;
2023-03-10 16:19:02 +01:00
const auto PCURRENT = getGroupCurrent ( ) ;
const bool FULLSCREEN = PCURRENT - > m_bIsFullscreen ;
const auto WORKSPACE = g_pCompositor - > getWorkspaceByID ( PCURRENT - > m_iWorkspaceID ) ;
2023-02-19 22:07:32 +01:00
const auto PWINDOWSIZE = PCURRENT - > m_vRealSize . goalv ( ) ;
const auto PWINDOWPOS = PCURRENT - > m_vRealPosition . goalv ( ) ;
const auto CURRENTISFOCUS = PCURRENT = = g_pCompositor - > m_pLastWindow ;
2023-03-10 16:19:02 +01:00
if ( FULLSCREEN )
g_pCompositor - > setWindowFullscreen ( PCURRENT , false , WORKSPACE - > m_efFullscreenMode ) ;
2023-02-19 22:07:32 +01:00
PCURRENT - > setHidden ( true ) ;
2023-08-15 19:15:37 +02:00
pWindow - > setHidden ( false ) ; // can remove m_pLastWindow
2023-02-19 22:07:32 +01:00
g_pLayoutManager - > getCurrentLayout ( ) - > replaceWindowDataWith ( PCURRENT , pWindow ) ;
if ( PCURRENT - > m_bIsFloating ) {
pWindow - > m_vRealPosition . setValueAndWarp ( PWINDOWPOS ) ;
pWindow - > m_vRealSize . setValueAndWarp ( PWINDOWSIZE ) ;
}
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
if ( CURRENTISFOCUS )
g_pCompositor - > focusWindow ( pWindow ) ;
2023-03-10 16:19:02 +01:00
if ( FULLSCREEN )
g_pCompositor - > setWindowFullscreen ( pWindow , true , WORKSPACE - > m_efFullscreenMode ) ;
2023-06-14 19:44:51 +02:00
g_pHyprRenderer - > damageWindow ( pWindow ) ;
2023-02-19 22:07:32 +01:00
}
void CWindow : : insertWindowToGroup ( CWindow * pWindow ) {
2023-08-30 17:39:22 +02:00
const auto BEGINAT = this ;
const auto ENDAT = m_sGroupData . pNextWindow ;
2023-02-19 23:19:40 +01:00
2023-09-10 23:59:10 +02:00
if ( ! pWindow - > getDecorationByType ( DECORATION_GROUPBAR ) )
pWindow - > m_dWindowDecorations . emplace_back ( std : : make_unique < CHyprGroupBarDecoration > ( pWindow ) ) ;
2023-07-20 19:48:32 +02:00
if ( ! pWindow - > m_sGroupData . pNextWindow ) {
BEGINAT - > m_sGroupData . pNextWindow = pWindow ;
pWindow - > m_sGroupData . pNextWindow = ENDAT ;
pWindow - > m_sGroupData . head = false ;
2023-02-19 23:19:40 +01:00
return ;
}
2023-07-20 19:48:32 +02:00
const auto SHEAD = pWindow - > getGroupHead ( ) ;
const auto STAIL = pWindow - > getGroupTail ( ) ;
SHEAD - > m_sGroupData . head = false ;
BEGINAT - > m_sGroupData . pNextWindow = SHEAD ;
STAIL - > m_sGroupData . pNextWindow = ENDAT ;
2023-03-18 17:30:29 +01:00
}
2023-07-13 17:55:20 +02:00
CWindow * CWindow : : getGroupPrevious ( ) {
CWindow * curr = m_sGroupData . pNextWindow ;
while ( curr ! = this & & curr - > m_sGroupData . pNextWindow ! = this )
curr = curr - > m_sGroupData . pNextWindow ;
return curr ;
}
void CWindow : : switchWithWindowInGroup ( CWindow * pWindow ) {
if ( ! m_sGroupData . pNextWindow | | ! pWindow - > m_sGroupData . pNextWindow )
return ;
2023-07-20 19:48:32 +02:00
if ( m_sGroupData . pNextWindow = = pWindow ) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
getGroupPrevious ( ) - > m_sGroupData . pNextWindow = pWindow ;
m_sGroupData . pNextWindow = pWindow - > m_sGroupData . pNextWindow ;
pWindow - > m_sGroupData . pNextWindow = this ;
2023-07-13 17:55:20 +02:00
2023-07-20 19:48:32 +02:00
} else if ( pWindow - > m_sGroupData . pNextWindow = = this ) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
pWindow - > getGroupPrevious ( ) - > m_sGroupData . pNextWindow = this ;
pWindow - > m_sGroupData . pNextWindow = m_sGroupData . pNextWindow ;
m_sGroupData . pNextWindow = pWindow ;
2023-07-13 17:55:20 +02:00
2023-07-20 19:48:32 +02:00
} else { // A -> this -> B | C -> pWindow -> D >> A -> pWindow -> B | C -> this -> D
std : : swap ( m_sGroupData . pNextWindow , pWindow - > m_sGroupData . pNextWindow ) ;
std : : swap ( getGroupPrevious ( ) - > m_sGroupData . pNextWindow , pWindow - > getGroupPrevious ( ) - > m_sGroupData . pNextWindow ) ;
2023-07-13 17:55:20 +02:00
}
std : : swap ( m_sGroupData . head , pWindow - > m_sGroupData . head ) ;
2023-07-20 19:48:32 +02:00
std : : swap ( m_sGroupData . locked , pWindow - > m_sGroupData . locked ) ;
2023-07-13 17:55:20 +02:00
}
2023-03-18 17:30:29 +01:00
void CWindow : : updateGroupOutputs ( ) {
if ( ! m_sGroupData . pNextWindow )
return ;
CWindow * curr = m_sGroupData . pNextWindow ;
while ( curr ! = this ) {
curr - > m_iMonitorID = m_iMonitorID ;
curr - > moveToWorkspace ( m_iWorkspaceID ) ;
curr - > m_vRealPosition = m_vRealPosition . goalv ( ) ;
curr - > m_vRealSize = m_vRealSize . goalv ( ) ;
curr = curr - > m_sGroupData . pNextWindow ;
}
2023-04-14 16:03:53 +02:00
}
Vector2D CWindow : : middle ( ) {
return m_vRealPosition . goalv ( ) + m_vRealSize . goalv ( ) / 2.f ;
}
2023-04-22 13:36:50 +02:00
bool CWindow : : opaque ( ) {
2023-07-19 16:13:55 +02:00
if ( m_fAlpha . fl ( ) ! = 1.f | | m_fActiveInactiveAlpha . fl ( ) ! = 1.f )
return false ;
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( m_iWorkspaceID ) ;
2023-10-20 21:15:41 +02:00
if ( m_pWLSurface . small ( ) & & ! m_pWLSurface . m_bFillIgnoreSmall )
return false ;
2023-07-19 16:13:55 +02:00
if ( PWORKSPACE - > m_fAlpha . fl ( ) ! = 1.f )
return false ;
2023-04-22 13:36:50 +02:00
if ( m_bIsX11 )
return ! m_uSurface . xwayland - > has_alpha ;
if ( m_uSurface . xdg - > surface - > opaque )
return true ;
const auto EXTENTS = pixman_region32_extents ( & m_uSurface . xdg - > surface - > opaque_region ) ;
2023-05-26 13:44:59 +02:00
if ( EXTENTS - > x2 - EXTENTS - > x1 > = m_uSurface . xdg - > surface - > current . buffer_width & & EXTENTS - > y2 - EXTENTS - > y1 > = m_uSurface . xdg - > surface - > current . buffer_height )
2023-04-22 13:36:50 +02:00
return true ;
return false ;
}
2023-07-19 16:13:55 +02:00
float CWindow : : rounding ( ) {
static auto * const PROUNDING = & g_pConfigManager - > getConfigValuePtr ( " decoration:rounding " ) - > intValue ;
float rounding = m_sAdditionalConfigData . rounding . toUnderlying ( ) = = - 1 ? * PROUNDING : m_sAdditionalConfigData . rounding . toUnderlying ( ) ;
return rounding ;
}
2023-08-17 10:13:19 +02:00
void CWindow : : updateSpecialRenderData ( ) {
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( m_iWorkspaceID ) ;
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager - > getWorkspaceRuleFor ( PWORKSPACE ) : SWorkspaceRule { } ;
bool border = true ;
if ( m_bIsFloating & & g_pConfigManager - > getConfigValuePtr ( " general:no_border_on_floating " ) - > intValue = = 1 )
border = false ;
m_sSpecialRenderData . border = WORKSPACERULE . border . value_or ( border ) ;
m_sSpecialRenderData . borderSize = WORKSPACERULE . borderSize . value_or ( - 1 ) ;
m_sSpecialRenderData . decorate = WORKSPACERULE . decorate . value_or ( true ) ;
m_sSpecialRenderData . rounding = WORKSPACERULE . rounding . value_or ( true ) ;
m_sSpecialRenderData . shadow = WORKSPACERULE . shadow . value_or ( true ) ;
}
int CWindow : : getRealBorderSize ( ) {
if ( ! m_sSpecialRenderData . border | | m_sAdditionalConfigData . forceNoBorder )
return 0 ;
if ( m_sAdditionalConfigData . borderSize . toUnderlying ( ) ! = - 1 )
return m_sAdditionalConfigData . borderSize . toUnderlying ( ) ;
if ( m_sSpecialRenderData . borderSize . toUnderlying ( ) ! = - 1 )
return m_sSpecialRenderData . borderSize . toUnderlying ( ) ;
return g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
}
2023-09-28 22:48:33 +02:00
bool CWindow : : canBeTorn ( ) {
return ( m_sAdditionalConfigData . forceTearing . toUnderlying ( ) | | m_bTearingHint ) & & g_pHyprRenderer - > m_bTearingEnvSatisfied ;
}