2025-01-07 17:55:14 +00:00
# include <hyprutils/animation/AnimatedVariable.hpp>
2024-12-16 19:21:44 +01:00
# include <re2/re2.h>
2024-05-29 05:37:24 +08:00
# include <any>
2024-08-03 12:02:10 +00:00
# include <bit>
2024-05-29 05:37:24 +08:00
# include <string_view>
# include <algorithm>
2022-03-30 21:18:42 +02:00
# include "Window.hpp"
2024-03-20 01:44:51 +00:00
# include "../Compositor.hpp"
# include "../render/decorations/CHyprDropShadowDecoration.hpp"
# include "../render/decorations/CHyprGroupBarDecoration.hpp"
# include "../render/decorations/CHyprBorderDecoration.hpp"
# include "../config/ConfigValue.hpp"
2024-04-23 01:28:20 +01:00
# include "../managers/TokenManager.hpp"
2025-01-07 17:55:14 +00:00
# include "../managers/AnimationManager.hpp"
2025-02-18 15:10:40 +00:00
# include "../managers/ANRManager.hpp"
2024-05-10 23:28:33 +01:00
# include "../protocols/XDGShell.hpp"
2024-06-08 10:07:59 +02:00
# include "../protocols/core/Compositor.hpp"
2025-02-02 22:25:29 +03:00
# include "../protocols/ContentType.hpp"
2025-04-06 00:30:13 +01:00
# include "../protocols/FractionalScale.hpp"
2024-05-25 22:43:51 +02:00
# include "../xwayland/XWayland.hpp"
2025-01-07 17:55:14 +00:00
# include "../helpers/Color.hpp"
2025-01-17 15:21:35 +00:00
# include "../events/Events.hpp"
# include "../managers/XWaylandManager.hpp"
# include "../render/Renderer.hpp"
# include "../managers/LayoutManager.hpp"
# include "../managers/HookSystemManager.hpp"
# include "../managers/EventManager.hpp"
# include "../managers/input/InputManager.hpp"
2022-03-30 21:18:42 +02:00
2024-06-11 17:17:45 +02:00
# include <hyprutils/string/String.hpp>
2025-01-07 17:55:14 +00:00
2024-06-11 17:17:45 +02:00
using namespace Hyprutils : : String ;
2025-01-07 17:55:14 +00:00
using namespace Hyprutils : : Animation ;
2025-02-02 22:25:29 +03:00
using enum NContentType : : eContentType ;
2024-06-11 17:17:45 +02:00
2024-05-25 22:43:51 +02:00
PHLWINDOW CWindow : : create ( SP < CXWaylandSurface > surface ) {
PHLWINDOW pWindow = SP < CWindow > ( new CWindow ( surface ) ) ;
2024-04-27 12:43:12 +01:00
2024-08-30 14:12:23 +02:00
pWindow - > m_pSelf = pWindow ;
pWindow - > m_bIsX11 = true ;
2024-04-27 12:43:12 +01:00
2025-01-07 17:55:14 +00:00
g_pAnimationManager - > createAnimation ( Vector2D ( 0 , 0 ) , pWindow - > m_vRealPosition , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( Vector2D ( 0 , 0 ) , pWindow - > m_vRealSize , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fBorderFadeAnimationProgress , g_pConfigManager - > getAnimationPropertyConfig ( " border " ) , pWindow , AVARDAMAGE_BORDER ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fBorderAngleAnimationProgress , g_pConfigManager - > getAnimationPropertyConfig ( " borderangle " ) , pWindow , AVARDAMAGE_BORDER ) ;
g_pAnimationManager - > createAnimation ( 1.f , pWindow - > m_fAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 1.f , pWindow - > m_fActiveInactiveAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeSwitch " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( CHyprColor ( ) , pWindow - > m_cRealShadowColor , g_pConfigManager - > getAnimationPropertyConfig ( " fadeShadow " ) , pWindow , AVARDAMAGE_SHADOW ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fDimPercent , g_pConfigManager - > getAnimationPropertyConfig ( " fadeDim " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fMovingToWorkspaceAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeOut " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fMovingFromWorkspaceAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
2025-02-18 15:10:40 +00:00
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_notRespondingTint , g_pConfigManager - > getAnimationPropertyConfig ( " fade " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
2024-04-27 12:43:12 +01:00
2025-01-23 21:55:41 +01:00
pWindow - > addWindowDeco ( makeUnique < CHyprDropShadowDecoration > ( pWindow ) ) ;
pWindow - > addWindowDeco ( makeUnique < CHyprBorderDecoration > ( pWindow ) ) ;
2022-06-25 20:28:40 +02:00
2024-04-27 12:43:12 +01:00
return pWindow ;
}
2024-05-10 23:28:33 +01:00
PHLWINDOW CWindow : : create ( SP < CXDGSurfaceResource > resource ) {
PHLWINDOW pWindow = SP < CWindow > ( new CWindow ( resource ) ) ;
pWindow - > m_pSelf = pWindow ;
resource - > toplevel - > window = pWindow ;
2025-01-07 17:55:14 +00:00
g_pAnimationManager - > createAnimation ( Vector2D ( 0 , 0 ) , pWindow - > m_vRealPosition , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( Vector2D ( 0 , 0 ) , pWindow - > m_vRealSize , g_pConfigManager - > getAnimationPropertyConfig ( " windowsIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fBorderFadeAnimationProgress , g_pConfigManager - > getAnimationPropertyConfig ( " border " ) , pWindow , AVARDAMAGE_BORDER ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fBorderAngleAnimationProgress , g_pConfigManager - > getAnimationPropertyConfig ( " borderangle " ) , pWindow , AVARDAMAGE_BORDER ) ;
g_pAnimationManager - > createAnimation ( 1.f , pWindow - > m_fAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 1.f , pWindow - > m_fActiveInactiveAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeSwitch " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( CHyprColor ( ) , pWindow - > m_cRealShadowColor , g_pConfigManager - > getAnimationPropertyConfig ( " fadeShadow " ) , pWindow , AVARDAMAGE_SHADOW ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fDimPercent , g_pConfigManager - > getAnimationPropertyConfig ( " fadeDim " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fMovingToWorkspaceAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeOut " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_fMovingFromWorkspaceAlpha , g_pConfigManager - > getAnimationPropertyConfig ( " fadeIn " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
2025-02-18 15:10:40 +00:00
g_pAnimationManager - > createAnimation ( 0.f , pWindow - > m_notRespondingTint , g_pConfigManager - > getAnimationPropertyConfig ( " fade " ) , pWindow , AVARDAMAGE_ENTIRE ) ;
2024-05-10 23:28:33 +01:00
2025-01-23 21:55:41 +01:00
pWindow - > addWindowDeco ( makeUnique < CHyprDropShadowDecoration > ( pWindow ) ) ;
pWindow - > addWindowDeco ( makeUnique < CHyprBorderDecoration > ( pWindow ) ) ;
2024-05-10 23:28:33 +01:00
2024-06-08 10:07:59 +02:00
pWindow - > m_pWLSurface - > assign ( pWindow - > m_pXDGSurface - > surface . lock ( ) , pWindow ) ;
2024-05-10 23:28:33 +01:00
return pWindow ;
}
CWindow : : CWindow ( SP < CXDGSurfaceResource > resource ) : m_pXDGSurface ( resource ) {
2024-06-08 10:07:59 +02:00
m_pWLSurface = CWLSurface : : create ( ) ;
2024-05-10 23:28:33 +01:00
listeners . map = m_pXDGSurface - > events . map . registerListener ( [ this ] ( std : : any d ) { Events : : listener_mapWindow ( this , nullptr ) ; } ) ;
listeners . ack = m_pXDGSurface - > events . ack . registerListener ( [ this ] ( std : : any d ) { onAck ( std : : any_cast < uint32_t > ( d ) ) ; } ) ;
listeners . unmap = m_pXDGSurface - > events . unmap . registerListener ( [ this ] ( std : : any d ) { Events : : listener_unmapWindow ( this , nullptr ) ; } ) ;
listeners . destroy = m_pXDGSurface - > events . destroy . registerListener ( [ this ] ( std : : any d ) { Events : : listener_destroyWindow ( this , nullptr ) ; } ) ;
listeners . commit = m_pXDGSurface - > events . commit . registerListener ( [ this ] ( std : : any d ) { Events : : listener_commitWindow ( this , nullptr ) ; } ) ;
listeners . updateState = m_pXDGSurface - > toplevel - > events . stateChanged . registerListener ( [ this ] ( std : : any d ) { onUpdateState ( ) ; } ) ;
listeners . updateMetadata = m_pXDGSurface - > toplevel - > events . metadataChanged . registerListener ( [ this ] ( std : : any d ) { onUpdateMeta ( ) ; } ) ;
}
2024-05-25 22:43:51 +02:00
CWindow : : CWindow ( SP < CXWaylandSurface > surface ) : m_pXWaylandSurface ( surface ) {
2024-06-08 10:07:59 +02:00
m_pWLSurface = CWLSurface : : create ( ) ;
2025-02-16 00:20:42 +00:00
listeners . map = m_pXWaylandSurface - > events . map . registerListener ( [ this ] ( std : : any d ) { Events : : listener_mapWindow ( this , nullptr ) ; } ) ;
listeners . unmap = m_pXWaylandSurface - > events . unmap . registerListener ( [ this ] ( std : : any d ) { Events : : listener_unmapWindow ( this , nullptr ) ; } ) ;
listeners . destroy = m_pXWaylandSurface - > events . destroy . registerListener ( [ this ] ( std : : any d ) { Events : : listener_destroyWindow ( this , nullptr ) ; } ) ;
listeners . commit = m_pXWaylandSurface - > events . commit . registerListener ( [ this ] ( std : : any d ) { Events : : listener_commitWindow ( this , nullptr ) ; } ) ;
listeners . configureRequest = m_pXWaylandSurface - > events . configureRequest . registerListener ( [ this ] ( std : : any d ) { onX11ConfigureRequest ( std : : any_cast < CBox > ( d ) ) ; } ) ;
listeners . updateState = m_pXWaylandSurface - > events . stateChanged . registerListener ( [ this ] ( std : : any d ) { onUpdateState ( ) ; } ) ;
listeners . updateMetadata = m_pXWaylandSurface - > events . metadataChanged . registerListener ( [ this ] ( std : : any d ) { onUpdateMeta ( ) ; } ) ;
listeners . resourceChange = m_pXWaylandSurface - > events . resourceChange . registerListener ( [ this ] ( std : : any d ) { onResourceChangeX11 ( ) ; } ) ;
listeners . activate = m_pXWaylandSurface - > events . activate . registerListener ( [ this ] ( std : : any d ) { Events : : listener_activateX11 ( this , nullptr ) ; } ) ;
2024-05-25 22:43:51 +02:00
if ( m_pXWaylandSurface - > overrideRedirect )
listeners . setGeometry = m_pXWaylandSurface - > events . setGeometry . registerListener ( [ this ] ( std : : any d ) { Events : : listener_unmanagedSetGeometry ( this , nullptr ) ; } ) ;
2022-04-23 14:16:02 +02:00
}
2022-03-30 21:18:42 +02:00
CWindow : : ~ CWindow ( ) {
2025-03-02 02:19:35 +00:00
if ( g_pCompositor - > m_pLastWindow = = m_pSelf ) {
2024-06-08 10:07:59 +02:00
g_pCompositor - > m_pLastFocus . reset ( ) ;
2024-04-27 12:43:12 +01:00
g_pCompositor - > m_pLastWindow . reset ( ) ;
2022-04-02 18:57:09 +02:00
}
2023-12-04 01:44:06 +00:00
2024-04-21 16:28:50 +01:00
events . destroy . emit ( ) ;
2023-12-06 14:46:18 +00:00
if ( ! g_pHyprOpenGL )
return ;
2023-12-04 01:44:06 +00:00
g_pHyprRenderer - > makeEGLCurrent ( ) ;
2025-03-02 02:19:35 +00:00
std : : erase_if ( g_pHyprOpenGL - > m_mWindowFramebuffers , [ & ] ( const auto & other ) { return other . first . expired ( ) | | other . first . get ( ) = = this ; } ) ;
2022-05-30 14:55:42 +02:00
}
2024-06-19 16:20:06 +02:00
SBoxExtents CWindow : : getFullWindowExtents ( ) {
2023-08-09 14:28:04 +02:00
if ( m_bFadingOut )
return m_eOriginalClosedExtents ;
2023-08-17 08:13:19 +00:00
const int BORDERSIZE = getRealBorderSize ( ) ;
2023-07-23 13:49:49 +00:00
2024-07-11 14:10:42 +00:00
if ( m_sWindowData . dimAround . valueOrDefault ( ) ) {
2024-10-27 18:45:38 +00:00
if ( const auto PMONITOR = m_pMonitor . lock ( ) ; PMONITOR )
2025-01-07 17:55:14 +00:00
return { { m_vRealPosition - > value ( ) . x - PMONITOR - > vecPosition . x , m_vRealPosition - > value ( ) . y - PMONITOR - > vecPosition . y } ,
{ PMONITOR - > vecSize . x - ( m_vRealPosition - > value ( ) . x - PMONITOR - > vecPosition . x ) , PMONITOR - > vecSize . y - ( m_vRealPosition - > value ( ) . y - PMONITOR - > vecPosition . y ) } } ;
2022-12-31 19:23:02 +01:00
}
2022-05-30 14:55:42 +02:00
2024-06-19 16:20:06 +02:00
SBoxExtents maxExtents = { { BORDERSIZE + 2 , BORDERSIZE + 2 } , { BORDERSIZE + 2 , BORDERSIZE + 2 } } ;
2022-05-30 14:55:42 +02:00
2024-06-19 16:20:06 +02:00
const auto EXTENTS = g_pDecorationPositioner - > getWindowDecorationExtents ( m_pSelf . lock ( ) ) ;
2022-05-30 14:55:42 +02:00
2023-11-11 14:37:17 +00:00
if ( EXTENTS . topLeft . x > maxExtents . topLeft . x )
maxExtents . topLeft . x = EXTENTS . topLeft . x ;
2022-05-30 14:55:42 +02:00
2023-11-11 14:37:17 +00:00
if ( EXTENTS . topLeft . y > maxExtents . topLeft . y )
maxExtents . topLeft . y = EXTENTS . topLeft . y ;
2022-05-30 14:55:42 +02:00
2023-11-11 14:37:17 +00:00
if ( EXTENTS . bottomRight . x > maxExtents . bottomRight . x )
maxExtents . bottomRight . x = EXTENTS . bottomRight . x ;
2022-05-30 14:55:42 +02:00
2023-11-11 14:37:17 +00:00
if ( EXTENTS . bottomRight . y > maxExtents . bottomRight . y )
maxExtents . bottomRight . y = EXTENTS . bottomRight . y ;
2022-05-30 14:55:42 +02:00
2024-06-08 10:07:59 +02:00
if ( m_pWLSurface - > exists ( ) & & ! m_bIsX11 & & m_pPopupHead ) {
2023-11-04 17:03:05 +00:00
CBox surfaceExtents = { 0 , 0 , 0 , 0 } ;
2023-06-23 13:54:01 +02:00
// TODO: this could be better, perhaps make a getFullWindowRegion?
2024-05-10 23:28:33 +01:00
m_pPopupHead - > breadthfirst (
2025-01-26 12:54:32 +00:00
[ ] ( WP < CPopup > popup , void * data ) {
2024-06-08 10:07:59 +02:00
if ( ! popup - > m_pWLSurface | | ! popup - > m_pWLSurface - > resource ( ) )
2024-05-10 23:28:33 +01:00
return ;
2023-11-04 17:03:05 +00:00
CBox * pSurfaceExtents = ( CBox * ) data ;
2024-05-10 23:28:33 +01:00
CBox surf = CBox { popup - > coordsRelativeToParent ( ) , popup - > size ( ) } ;
if ( surf . x < pSurfaceExtents - > x )
pSurfaceExtents - > x = surf . x ;
if ( surf . y < pSurfaceExtents - > y )
pSurfaceExtents - > y = surf . y ;
if ( surf . x + surf . w > pSurfaceExtents - > width )
pSurfaceExtents - > width = surf . x + surf . w - pSurfaceExtents - > x ;
if ( surf . y + surf . h > pSurfaceExtents - > height )
pSurfaceExtents - > height = surf . y + surf . h - pSurfaceExtents - > y ;
2023-06-23 13:54:01 +02:00
} ,
& surfaceExtents ) ;
if ( - surfaceExtents . x > maxExtents . topLeft . x )
maxExtents . topLeft . x = - surfaceExtents . x ;
if ( - surfaceExtents . y > maxExtents . topLeft . y )
maxExtents . topLeft . y = - surfaceExtents . y ;
2024-06-08 10:07:59 +02:00
if ( surfaceExtents . x + surfaceExtents . width > m_pWLSurface - > resource ( ) - > current . size . x + maxExtents . bottomRight . x )
maxExtents . bottomRight . x = surfaceExtents . x + surfaceExtents . width - m_pWLSurface - > resource ( ) - > current . size . x ;
2023-06-23 13:54:01 +02:00
2024-06-08 10:07:59 +02:00
if ( surfaceExtents . y + surfaceExtents . height > m_pWLSurface - > resource ( ) - > current . size . y + maxExtents . bottomRight . y )
maxExtents . bottomRight . y = surfaceExtents . y + surfaceExtents . height - m_pWLSurface - > resource ( ) - > current . size . y ;
2023-06-23 13:54:01 +02:00
}
2023-08-09 14:28:04 +02:00
return maxExtents ;
}
2023-11-04 17:03:05 +00:00
CBox CWindow : : getFullWindowBoundingBox ( ) {
2024-07-11 14:10:42 +00:00
if ( m_sWindowData . dimAround . valueOrDefault ( ) ) {
2024-10-27 18:45:38 +00:00
if ( const auto PMONITOR = m_pMonitor . lock ( ) ; PMONITOR )
2024-05-22 22:37:02 +02:00
return { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
2023-08-09 14:28:04 +02:00
}
2023-11-04 17:03:05 +00:00
auto maxExtents = getFullWindowExtents ( ) ;
2023-08-09 14:28:04 +02:00
2025-01-07 17:55:14 +00:00
CBox finalBox = { m_vRealPosition - > value ( ) . x - maxExtents . topLeft . x , m_vRealPosition - > value ( ) . y - maxExtents . topLeft . y ,
m_vRealSize - > value ( ) . x + maxExtents . topLeft . x + maxExtents . bottomRight . x , m_vRealSize - > value ( ) . 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
}
2023-11-04 17:03:05 +00:00
CBox CWindow : : getWindowIdealBoundingBoxIgnoreReserved ( ) {
2024-10-27 18:45:38 +00:00
const auto PMONITOR = m_pMonitor . lock ( ) ;
2022-06-23 20:39:48 +02:00
2024-06-03 21:09:18 +02:00
if ( ! PMONITOR )
return { m_vPosition , m_vSize } ;
auto POS = m_vPosition ;
auto SIZE = m_vSize ;
2022-06-23 20:39:48 +02:00
2024-07-31 17:55:52 +00:00
if ( isFullscreen ( ) ) {
2022-12-16 17:17:31 +00:00
POS = PMONITOR - > vecPosition ;
2022-11-21 23:33:23 +00:00
SIZE = PMONITOR - > vecSize ;
2023-11-04 17:03:05 +00:00
return CBox { ( int ) POS . x , ( int ) POS . y , ( int ) SIZE . x , ( int ) SIZE . y } ;
2022-11-21 23:33:23 +00:00
}
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 ;
}
2023-11-04 17:03:05 +00:00
return CBox { ( int ) POS . x , ( int ) POS . y , ( int ) SIZE . x , ( int ) SIZE . y } ;
2022-06-27 00:25:37 +02:00
}
2024-02-04 15:40:20 +00:00
CBox CWindow : : getWindowBoxUnified ( uint64_t properties ) {
2024-07-11 14:10:42 +00:00
if ( m_sWindowData . dimAround . valueOrDefault ( ) ) {
2024-10-27 18:45:38 +00:00
const auto PMONITOR = m_pMonitor . lock ( ) ;
2024-06-03 21:09:18 +02:00
if ( PMONITOR )
return { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
2023-02-28 22:32:42 +00:00
}
2024-06-19 16:20:06 +02:00
SBoxExtents EXTENTS = { { 0 , 0 } , { 0 , 0 } } ;
2024-02-04 15:40:20 +00:00
if ( properties & RESERVED_EXTENTS )
2024-04-27 12:43:12 +01:00
EXTENTS . addExtents ( g_pDecorationPositioner - > getWindowDecorationReserved ( m_pSelf . lock ( ) ) ) ;
2024-02-04 15:40:20 +00:00
if ( properties & INPUT_EXTENTS )
2024-04-27 12:43:12 +01:00
EXTENTS . addExtents ( g_pDecorationPositioner - > getWindowDecorationExtents ( m_pSelf . lock ( ) , true ) ) ;
2024-02-04 15:40:20 +00:00
if ( properties & FULL_EXTENTS )
2024-04-27 12:43:12 +01:00
EXTENTS . addExtents ( g_pDecorationPositioner - > getWindowDecorationExtents ( m_pSelf . lock ( ) , false ) ) ;
2023-02-28 22:32:42 +00:00
2025-01-07 17:55:14 +00:00
CBox box = { m_vRealPosition - > value ( ) . x , m_vRealPosition - > value ( ) . y , m_vRealSize - > value ( ) . x , m_vRealSize - > value ( ) . y } ;
2024-02-04 15:40:20 +00:00
box . addExtents ( EXTENTS ) ;
2023-02-28 22:32:42 +00:00
2024-02-04 15:40:20 +00:00
return box ;
2023-02-28 22:32:42 +00:00
}
2024-06-19 16:20:06 +02:00
SBoxExtents CWindow : : getFullWindowReservedArea ( ) {
2024-04-27 12:43:12 +01:00
return g_pDecorationPositioner - > getWindowDecorationReserved ( m_pSelf . lock ( ) ) ;
2023-02-28 19:36:36 +00:00
}
2022-06-27 00:25:37 +02:00
void CWindow : : updateWindowDecos ( ) {
2023-06-05 09:49:17 +02:00
2023-11-11 14:37:17 +00:00
if ( ! m_bIsMapped | | isHidden ( ) )
return ;
2024-08-26 17:25:39 +02:00
for ( auto const & wd : m_vDecosToRemove ) {
2022-07-05 17:31:47 +02:00
for ( auto it = m_dWindowDecorations . begin ( ) ; it ! = m_dWindowDecorations . end ( ) ; it + + ) {
if ( it - > get ( ) = = wd ) {
2023-11-11 14:37:17 +00:00
g_pDecorationPositioner - > uncacheDecoration ( it - > get ( ) ) ;
2024-05-01 07:59:40 -04:00
it = m_dWindowDecorations . erase ( it ) ;
2022-07-05 17:31:47 +02:00
if ( it = = m_dWindowDecorations . end ( ) )
break ;
}
}
}
2024-04-27 12:43:12 +01:00
g_pDecorationPositioner - > onWindowUpdate ( m_pSelf . lock ( ) ) ;
2023-11-11 14:37:17 +00:00
2022-07-05 17:31:47 +02:00
m_vDecosToRemove . clear ( ) ;
2023-11-11 14:37:17 +00:00
2024-03-10 16:56:32 +00:00
// make a copy because updateWindow can remove decos.
std : : vector < IHyprWindowDecoration * > decos ;
2025-01-19 10:38:42 +00:00
// reserve to avoid reallocations
decos . reserve ( m_dWindowDecorations . size ( ) ) ;
2024-03-10 16:56:32 +00:00
2024-08-26 17:25:39 +02:00
for ( auto const & wd : m_dWindowDecorations ) {
2024-03-10 16:56:32 +00:00
decos . push_back ( wd . get ( ) ) ;
}
2024-08-26 17:25:39 +02:00
for ( auto const & wd : decos ) {
2024-05-07 16:50:30 +01:00
if ( std : : find_if ( m_dWindowDecorations . begin ( ) , m_dWindowDecorations . end ( ) , [ wd ] ( const auto & other ) { return other . get ( ) = = wd ; } ) = = m_dWindowDecorations . end ( ) )
continue ;
2024-04-27 12:43:12 +01:00
wd - > updateWindow ( m_pSelf . lock ( ) ) ;
2023-11-11 14:37:17 +00:00
}
}
2025-01-23 21:55:41 +01:00
void CWindow : : addWindowDeco ( UP < IHyprWindowDecoration > deco ) {
2023-11-11 14:37:17 +00:00
m_dWindowDecorations . emplace_back ( std : : move ( deco ) ) ;
2024-04-27 12:43:12 +01:00
g_pDecorationPositioner - > forceRecalcFor ( m_pSelf . lock ( ) ) ;
2023-11-11 14:37:17 +00:00
updateWindowDecos ( ) ;
2024-04-27 12:43:12 +01:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateWindow ( m_pSelf . lock ( ) ) ;
2023-11-11 14:37:17 +00:00
}
void CWindow : : removeWindowDeco ( IHyprWindowDecoration * deco ) {
m_vDecosToRemove . push_back ( deco ) ;
2024-04-27 12:43:12 +01:00
g_pDecorationPositioner - > forceRecalcFor ( m_pSelf . lock ( ) ) ;
2023-11-11 14:37:17 +00:00
updateWindowDecos ( ) ;
2024-04-27 12:43:12 +01:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateWindow ( m_pSelf . lock ( ) ) ;
2022-06-27 13:42:20 +02:00
}
2023-12-30 14:18:53 +00:00
void CWindow : : uncacheWindowDecos ( ) {
2024-08-26 20:24:30 +02:00
for ( auto const & wd : m_dWindowDecorations ) {
2023-12-30 14:18:53 +00:00
g_pDecorationPositioner - > uncacheDecoration ( wd . get ( ) ) ;
}
}
2023-12-28 22:54:41 +00:00
bool CWindow : : checkInputOnDecos ( const eInputType type , const Vector2D & mouseCoords , std : : any data ) {
if ( type ! = INPUT_TYPE_DRAG_END & & hasPopupAt ( mouseCoords ) )
return false ;
2024-08-26 20:24:30 +02:00
for ( auto const & wd : m_dWindowDecorations ) {
2023-12-28 22:54:41 +00:00
if ( ! ( wd - > getDecorationFlags ( ) & DECORATION_ALLOWS_MOUSE_INPUT ) )
continue ;
if ( ! g_pDecorationPositioner - > getWindowDecorationBox ( wd . get ( ) ) . containsPoint ( mouseCoords ) )
continue ;
if ( wd - > onInputOnDeco ( type , mouseCoords , data ) )
return true ;
}
return false ;
}
2022-06-27 13:42:20 +02:00
pid_t CWindow : : getPID ( ) {
pid_t PID = - 1 ;
if ( ! m_bIsX11 ) {
2024-05-10 23:28:33 +01:00
if ( ! m_pXDGSurface | | ! m_pXDGSurface - > owner /* happens at unmap */ )
2023-03-03 11:17:43 +00:00
return - 1 ;
2024-05-10 23:28:33 +01:00
wl_client_get_credentials ( m_pXDGSurface - > owner - > client ( ) , & PID , nullptr , nullptr ) ;
2022-06-27 13:42:20 +02:00
} else {
2024-05-25 22:43:51 +02:00
if ( ! m_pXWaylandSurface )
2023-11-01 18:53:36 +00:00
return - 1 ;
2024-05-25 22:43:51 +02:00
PID = m_pXWaylandSurface - > pid ;
2022-06-27 13:42:20 +02:00
}
return PID ;
}
2022-07-16 12:44:45 +02:00
IHyprWindowDecoration * CWindow : : getDecorationByType ( eDecorationType type ) {
2024-08-26 20:24:30 +02:00
for ( auto const & wd : m_dWindowDecorations ) {
2022-07-16 12:44:45 +02:00
if ( wd - > getDecorationType ( ) = = type )
return wd . get ( ) ;
}
return nullptr ;
2022-08-06 20:57:38 +02:00
}
void CWindow : : updateToplevel ( ) {
2024-01-09 18:14:08 +01:00
updateSurfaceScaleTransformDetails ( ) ;
2022-08-08 21:20:41 +02:00
}
2024-06-08 10:07:59 +02:00
void CWindow : : updateSurfaceScaleTransformDetails ( bool force ) {
2024-03-05 20:46:08 +00:00
if ( ! m_bIsMapped | | m_bHidden | | g_pCompositor - > m_bUnsafeState )
2022-08-08 21:20:41 +02:00
return ;
const auto PLASTMONITOR = g_pCompositor - > getMonitorFromID ( m_iLastSurfaceMonitorID ) ;
2024-10-27 18:45:38 +00:00
m_iLastSurfaceMonitorID = monitorID ( ) ;
2022-08-08 21:20:41 +02:00
2024-10-27 18:45:38 +00:00
const auto PNEWMONITOR = m_pMonitor . lock ( ) ;
2022-08-08 21:20:41 +02:00
2024-03-05 20:46:08 +00:00
if ( ! PNEWMONITOR )
return ;
2024-06-08 10:07:59 +02:00
if ( PNEWMONITOR ! = PLASTMONITOR | | force ) {
if ( PLASTMONITOR & & PLASTMONITOR - > m_bEnabled & & PNEWMONITOR ! = PLASTMONITOR )
m_pWLSurface - > resource ( ) - > breadthfirst ( [ PLASTMONITOR ] ( SP < CWLSurfaceResource > s , const Vector2D & offset , void * d ) { s - > leave ( PLASTMONITOR - > self . lock ( ) ) ; } , nullptr ) ;
2022-08-08 21:20:41 +02:00
2024-06-08 10:07:59 +02:00
m_pWLSurface - > resource ( ) - > breadthfirst ( [ PNEWMONITOR ] ( SP < CWLSurfaceResource > s , const Vector2D & offset , void * d ) { s - > enter ( PNEWMONITOR - > self . lock ( ) ) ; } , nullptr ) ;
2024-01-09 18:14:08 +01:00
}
2023-06-06 09:48:07 +02:00
2024-10-27 18:45:38 +00:00
const auto PMONITOR = m_pMonitor . lock ( ) ;
2024-01-11 13:15:20 +01:00
2024-10-27 18:45:38 +00:00
m_pWLSurface - > resource ( ) - > breadthfirst (
[ PMONITOR ] ( SP < CWLSurfaceResource > s , const Vector2D & offset , void * d ) {
2024-06-08 10:07:59 +02:00
const auto PSURFACE = CWLSurface : : fromResource ( s ) ;
2024-01-11 13:15:20 +01:00
if ( PSURFACE & & PSURFACE - > m_fLastScale = = PMONITOR - > scale )
return ;
2025-04-06 00:30:13 +01:00
PROTO : : fractional - > sendScale ( s , PMONITOR - > scale ) ;
2024-06-08 10:07:59 +02:00
g_pCompositor - > setPreferredScaleForSurface ( s , PMONITOR - > scale ) ;
g_pCompositor - > setPreferredTransformForSurface ( s , PMONITOR - > transform ) ;
2023-06-06 09:48:07 +02:00
} ,
2024-06-08 10:07:59 +02:00
nullptr ) ;
2022-08-21 18:01:26 +03:00
}
2024-04-02 20:32:39 +01:00
void CWindow : : moveToWorkspace ( PHLWORKSPACE pWorkspace ) {
if ( m_pWorkspace = = pWorkspace )
2023-03-18 16:30:29 +00:00
return ;
2022-08-21 18:01:26 +03:00
2024-04-24 16:16:46 +01:00
static auto PINITIALWSTRACKING = CConfigValue < Hyprlang : : INT > ( " misc:initial_workspace_tracking " ) ;
2024-04-23 01:28:20 +01:00
if ( ! m_szInitialWorkspaceToken . empty ( ) ) {
2024-04-24 16:16:46 +01:00
const auto TOKEN = g_pTokenManager - > getToken ( m_szInitialWorkspaceToken ) ;
if ( TOKEN ) {
if ( * PINITIALWSTRACKING = = 2 ) {
// persistent
SInitialWorkspaceToken token = std : : any_cast < SInitialWorkspaceToken > ( TOKEN - > data ) ;
2025-03-02 02:19:35 +00:00
if ( token . primaryOwner = = m_pSelf ) {
2024-04-24 16:16:46 +01:00
token . workspace = pWorkspace - > getConfigName ( ) ;
TOKEN - > data = token ;
}
}
}
2024-04-23 01:28:20 +01:00
}
2024-03-03 18:39:20 +00:00
static auto PCLOSEONLASTSPECIAL = CConfigValue < Hyprlang : : INT > ( " misc:close_special_on_empty " ) ;
2023-10-24 00:58:44 +01:00
2025-01-25 19:37:33 +00:00
const auto OLDWORKSPACE = m_pWorkspace ;
2023-10-24 00:58:44 +01:00
2025-01-26 13:00:52 +00:00
if ( OLDWORKSPACE - > isVisible ( ) ) {
m_fMovingToWorkspaceAlpha - > setValueAndWarp ( 1.F ) ;
* m_fMovingToWorkspaceAlpha = 0.F ;
m_fMovingToWorkspaceAlpha - > setCallbackOnEnd ( [ this ] ( auto ) { m_iMonitorMovedFrom = - 1 ; } ) ;
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE - > monitorID ( ) : - 1 ;
}
2024-08-28 21:54:49 +02:00
2024-04-02 20:32:39 +01:00
m_pWorkspace = pWorkspace ;
2023-03-18 16:30:29 +00:00
2024-03-18 19:52:52 -07:00
setAnimationsToMove ( ) ;
2024-11-22 16:01:02 +00:00
OLDWORKSPACE - > updateWindows ( ) ;
OLDWORKSPACE - > updateWindowData ( ) ;
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( OLDWORKSPACE - > monitorID ( ) ) ;
2024-04-20 02:46:16 +09:00
2024-11-22 16:01:02 +00:00
pWorkspace - > updateWindows ( ) ;
pWorkspace - > updateWindowData ( ) ;
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
2024-04-20 02:46:16 +09:00
2024-04-11 01:26:11 +09:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2023-08-17 08:13:19 +00:00
2024-04-02 20:32:39 +01:00
if ( valid ( pWorkspace ) ) {
g_pEventManager - > postEvent ( SHyprIPCEvent { " movewindow " , std : : format ( " {:x},{} " , ( uintptr_t ) this , pWorkspace - > m_szName ) } ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " movewindowv2 " , std : : format ( " {:x},{},{} " , ( uintptr_t ) this , pWorkspace - > m_iID , pWorkspace - > m_szName ) } ) ;
2024-04-27 12:43:12 +01:00
EMIT_HOOK_EVENT ( " moveWindow " , ( std : : vector < std : : any > { m_pSelf . lock ( ) , pWorkspace } ) ) ;
2022-08-21 18:01:26 +03:00
}
2023-03-18 16:30:29 +00:00
2024-04-27 12:43:12 +01:00
if ( const auto SWALLOWED = m_pSwallowed . lock ( ) ) {
2025-02-05 10:56:41 +01:00
if ( SWALLOWED - > m_bCurrentlySwallowed ) {
SWALLOWED - > moveToWorkspace ( pWorkspace ) ;
SWALLOWED - > m_pMonitor = m_pMonitor ;
}
2023-04-02 10:24:17 +01:00
}
2023-08-15 19:15:37 +02:00
2024-11-22 16:01:02 +00:00
if ( OLDWORKSPACE & & g_pCompositor - > isWorkspaceSpecial ( OLDWORKSPACE - > m_iID ) & & OLDWORKSPACE - > getWindows ( ) = = 0 & & * PCLOSEONLASTSPECIAL ) {
2024-10-27 18:45:38 +00:00
if ( const auto PMONITOR = OLDWORKSPACE - > m_pMonitor . lock ( ) ; PMONITOR )
2024-04-02 20:32:39 +01:00
PMONITOR - > setSpecialWorkspace ( nullptr ) ;
2023-10-24 00:58:44 +01:00
}
2022-08-28 19:47:06 +02:00
}
2024-12-07 18:51:18 +01:00
PHLWINDOW CWindow : : x11TransientFor ( ) {
2024-05-25 22:43:51 +02:00
if ( ! m_pXWaylandSurface | | ! m_pXWaylandSurface - > parent )
2022-08-28 19:47:06 +02:00
return nullptr ;
2024-10-16 22:22:36 +01:00
auto s = m_pXWaylandSurface - > parent ;
std : : vector < SP < CXWaylandSurface > > visited ;
2024-05-25 22:43:51 +02:00
while ( s ) {
2024-10-16 22:22:36 +01:00
// break loops. Some X apps make them, and it seems like it's valid behavior?!?!?!
// TODO: we should reject loops being created in the first place.
if ( std : : find ( visited . begin ( ) , visited . end ( ) , s ) ! = visited . end ( ) )
2024-05-25 22:43:51 +02:00
break ;
2024-10-16 22:22:36 +01:00
visited . emplace_back ( s . lock ( ) ) ;
2024-05-25 22:43:51 +02:00
s = s - > parent ;
2022-08-28 19:47:06 +02:00
}
2024-10-16 22:22:36 +01:00
if ( s = = m_pXWaylandSurface )
return nullptr ; // dead-ass circle
2024-08-26 17:25:39 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-05-25 22:43:51 +02:00
if ( w - > m_pXWaylandSurface ! = s )
continue ;
return w ;
}
2022-09-01 10:16:23 +02:00
2024-05-25 22:43:51 +02:00
return nullptr ;
2022-08-28 19:47:06 +02:00
}
2022-08-29 19:52:35 +02:00
2022-10-14 20:46:32 +01:00
void CWindow : : onUnmap ( ) {
2024-03-03 18:39:20 +00:00
static auto PCLOSEONLASTSPECIAL = CConfigValue < Hyprlang : : INT > ( " misc:close_special_on_empty " ) ;
2024-07-27 16:46:19 +00:00
static auto PINITIALWSTRACKING = CConfigValue < Hyprlang : : INT > ( " misc:initial_workspace_tracking " ) ;
2024-04-24 16:16:46 +01:00
if ( ! m_szInitialWorkspaceToken . empty ( ) ) {
const auto TOKEN = g_pTokenManager - > getToken ( m_szInitialWorkspaceToken ) ;
if ( TOKEN ) {
if ( * PINITIALWSTRACKING = = 2 ) {
// persistent token, but the first window got removed so the token is gone
SInitialWorkspaceToken token = std : : any_cast < SInitialWorkspaceToken > ( TOKEN - > data ) ;
2025-03-02 02:19:35 +00:00
if ( token . primaryOwner = = m_pSelf )
2024-04-24 16:16:46 +01:00
g_pTokenManager - > removeToken ( TOKEN ) ;
}
}
}
2024-04-04 22:49:15 +01:00
m_iLastWorkspace = m_pWorkspace - > m_iID ;
2024-04-02 20:32:39 +01:00
2025-03-02 02:19:35 +00:00
std : : erase_if ( g_pCompositor - > m_vWindowFocusHistory , [ this ] ( const auto & other ) { return other . expired ( ) | | other = = m_pSelf ; } ) ;
2023-03-23 00:39:32 +00:00
2024-11-22 16:01:02 +00:00
if ( * PCLOSEONLASTSPECIAL & & m_pWorkspace & & m_pWorkspace - > getWindows ( ) = = 0 & & onSpecialWorkspace ( ) ) {
2024-10-27 18:45:38 +00:00
const auto PMONITOR = m_pMonitor . lock ( ) ;
2024-04-02 20:32:39 +01:00
if ( PMONITOR & & PMONITOR - > activeSpecialWorkspace & & PMONITOR - > activeSpecialWorkspace = = m_pWorkspace )
2023-09-03 13:00:02 +02:00
PMONITOR - > setSpecialWorkspace ( nullptr ) ;
}
2023-09-28 21:48:33 +01:00
2024-10-27 18:45:38 +00:00
const auto PMONITOR = m_pMonitor . lock ( ) ;
2023-09-28 21:48:33 +01:00
2025-03-02 02:19:35 +00:00
if ( PMONITOR & & PMONITOR - > solitaryClient = = m_pSelf )
2024-04-27 12:43:12 +01:00
PMONITOR - > solitaryClient . reset ( ) ;
2023-12-20 23:52:18 +01:00
2024-11-22 16:01:02 +00:00
if ( m_pWorkspace ) {
m_pWorkspace - > updateWindows ( ) ;
m_pWorkspace - > updateWindowData ( ) ;
}
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
2024-04-11 01:26:11 +09:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2024-02-29 00:03:28 +00:00
2024-04-12 19:52:01 +01:00
m_pWorkspace . reset ( ) ;
2024-02-29 14:26:02 +00:00
if ( m_bIsX11 )
return ;
2024-02-29 00:03:28 +00:00
m_pSubsurfaceHead . reset ( ) ;
2024-02-29 14:26:02 +00:00
m_pPopupHead . reset ( ) ;
2022-11-04 15:56:31 +00:00
}
void CWindow : : onMap ( ) {
2022-11-18 13:53:54 +00: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)
2025-01-07 17:55:14 +00:00
m_vRealPosition - > resetAllCallbacks ( ) ;
m_vRealSize - > resetAllCallbacks ( ) ;
m_fBorderFadeAnimationProgress - > resetAllCallbacks ( ) ;
m_fBorderAngleAnimationProgress - > resetAllCallbacks ( ) ;
m_fActiveInactiveAlpha - > resetAllCallbacks ( ) ;
m_fAlpha - > resetAllCallbacks ( ) ;
m_cRealShadowColor - > resetAllCallbacks ( ) ;
m_fDimPercent - > resetAllCallbacks ( ) ;
m_fMovingToWorkspaceAlpha - > resetAllCallbacks ( ) ;
m_fMovingFromWorkspaceAlpha - > resetAllCallbacks ( ) ;
m_fMovingFromWorkspaceAlpha - > setValueAndWarp ( 1.F ) ;
2025-01-25 18:23:36 +00:00
if ( m_fBorderAngleAnimationProgress - > enabled ( ) ) {
m_fBorderAngleAnimationProgress - > setValueAndWarp ( 0.f ) ;
m_fBorderAngleAnimationProgress - > setCallbackOnEnd ( [ & ] ( WP < CBaseAnimatedVariable > p ) { onBorderAngleAnimEnd ( p ) ; } , false ) ;
* m_fBorderAngleAnimationProgress = 1.f ;
}
2025-01-07 17:55:14 +00:00
2025-02-06 11:21:04 +00:00
m_vRealSize - > setCallbackOnBegin (
[ this ] ( auto ) {
if ( ! m_bIsMapped | | isX11OverrideRedirect ( ) )
return ;
sendWindowSize ( ) ;
} ,
false ) ;
2025-01-07 17:55:14 +00:00
m_fMovingFromWorkspaceAlpha - > setValueAndWarp ( 1.F ) ;
2024-12-22 16:04:10 +00:00
2024-04-27 12:43:12 +01:00
g_pCompositor - > m_vWindowFocusHistory . push_back ( m_pSelf ) ;
2023-03-28 20:17:47 +01:00
2023-10-20 20:15:41 +01:00
m_vReportedSize = m_vPendingReportedSize ;
2024-03-17 01:05:26 +00:00
m_bAnimatingIn = true ;
2024-02-01 00:55:17 +00:00
2024-06-08 10:07:59 +02:00
updateSurfaceScaleTransformDetails ( true ) ;
2024-02-29 14:26:02 +00:00
if ( m_bIsX11 )
return ;
2025-02-01 15:08:30 +00:00
m_pSubsurfaceHead = CSubsurface : : create ( m_pSelf . lock ( ) ) ;
m_pPopupHead = CPopup : : create ( m_pSelf . lock ( ) ) ;
2022-10-14 20:46:32 +01:00
}
2025-01-07 17:55:14 +00:00
void CWindow : : onBorderAngleAnimEnd ( WP < CBaseAnimatedVariable > pav ) {
const auto PAV = pav . lock ( ) ;
if ( ! PAV )
return ;
2023-02-01 16:06:01 -05:00
2025-01-07 17:55:14 +00:00
if ( PAV - > getStyle ( ) ! = " loop " | | ! PAV - > enabled ( ) )
2023-02-01 16:06:01 -05:00
return ;
2025-01-07 17:55:14 +00:00
const auto PANIMVAR = dynamic_cast < CAnimatedVariable < float > * > ( PAV . get ( ) ) ;
2023-02-01 16:06:01 -05:00
PANIMVAR - > setCallbackOnEnd ( nullptr ) ; // we remove the callback here because otherwise setvalueandwarp will recurse this
PANIMVAR - > setValueAndWarp ( 0 ) ;
* PANIMVAR = 1.f ;
2025-01-07 17:55:14 +00:00
PANIMVAR - > setCallbackOnEnd ( [ & ] ( WP < CBaseAnimatedVariable > pav ) { onBorderAngleAnimEnd ( pav ) ; } , false ) ;
2023-02-01 16:06:01 -05:00
}
2022-10-14 20:46:32 +01:00
void CWindow : : setHidden ( bool hidden ) {
m_bHidden = hidden ;
2025-03-02 02:19:35 +00:00
if ( hidden & & g_pCompositor - > m_pLastWindow = = m_pSelf )
2024-04-27 12:43:12 +01:00
g_pCompositor - > m_pLastWindow . reset ( ) ;
2023-12-23 22:30:49 +01:00
setSuspended ( hidden ) ;
2022-10-14 20:46:32 +01:00
}
bool CWindow : : isHidden ( ) {
return m_bHidden ;
2022-11-15 11:21:26 +01:00
}
2024-12-16 19:05:24 +01:00
void CWindow : : applyDynamicRule ( const SP < CWindowRule > & r ) {
const eOverridePriority priority = r - > execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE ;
switch ( r - > ruleType ) {
case CWindowRule : : RULE_TAG : {
CVarList vars { r - > szRule , 0 , ' s ' , true } ;
if ( vars . size ( ) = = 2 & & vars [ 0 ] = = " tag " )
m_tags . applyTag ( vars [ 1 ] , true ) ;
else
Debug : : log ( ERR , " Tag rule invalid: {} " , r - > szRule ) ;
break ;
}
case CWindowRule : : RULE_OPACITY : {
try {
CVarList vars ( r - > szRule , 0 , ' ' ) ;
int opacityIDX = 0 ;
for ( auto const & r : vars ) {
if ( r = = " opacity " )
continue ;
if ( r = = " override " ) {
if ( opacityIDX = = 1 )
m_sWindowData . alpha = CWindowOverridableVar ( SAlphaValue { m_sWindowData . alpha . value ( ) . m_fAlpha , true } , priority ) ;
else if ( opacityIDX = = 2 )
m_sWindowData . alphaInactive = CWindowOverridableVar ( SAlphaValue { m_sWindowData . alphaInactive . value ( ) . m_fAlpha , true } , priority ) ;
else if ( opacityIDX = = 3 )
m_sWindowData . alphaFullscreen = CWindowOverridableVar ( SAlphaValue { m_sWindowData . alphaFullscreen . value ( ) . m_fAlpha , true } , priority ) ;
2022-12-11 17:15:02 +00:00
} else {
2024-12-16 19:05:24 +01:00
if ( opacityIDX = = 0 ) {
m_sWindowData . alpha = CWindowOverridableVar ( SAlphaValue { std : : stof ( r ) , false } , priority ) ;
} else if ( opacityIDX = = 1 ) {
m_sWindowData . alphaInactive = CWindowOverridableVar ( SAlphaValue { std : : stof ( r ) , false } , priority ) ;
} else if ( opacityIDX = = 2 ) {
m_sWindowData . alphaFullscreen = CWindowOverridableVar ( SAlphaValue { std : : stof ( r ) , false } , priority ) ;
} else {
throw std : : runtime_error ( " more than 3 alpha values " ) ;
}
opacityIDX + + ;
2022-12-11 17:15:02 +00:00
}
}
2024-04-09 18:22:44 +03:00
2024-12-16 19:05:24 +01:00
if ( opacityIDX = = 1 ) {
m_sWindowData . alphaInactive = m_sWindowData . alpha ;
m_sWindowData . alphaFullscreen = m_sWindowData . alpha ;
}
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Opacity rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
break ;
}
case CWindowRule : : RULE_ANIMATION : {
auto STYLE = r - > szRule . substr ( r - > szRule . find_first_of ( ' ' ) + 1 ) ;
m_sWindowData . animationStyle = CWindowOverridableVar ( STYLE , priority ) ;
break ;
}
case CWindowRule : : RULE_BORDERCOLOR : {
try {
// Each vector will only get used if it has at least one color
CGradientValueData activeBorderGradient = { } ;
CGradientValueData inactiveBorderGradient = { } ;
bool active = true ;
CVarList colorsAndAngles = CVarList ( trim ( r - > szRule . substr ( r - > szRule . find_first_of ( ' ' ) + 1 ) ) , 0 , ' s ' , true ) ;
// Basic form has only two colors, everything else can be parsed as a gradient
if ( colorsAndAngles . size ( ) = = 2 & & ! colorsAndAngles [ 1 ] . contains ( " deg " ) ) {
m_sWindowData . activeBorderColor = CWindowOverridableVar ( CGradientValueData ( CHyprColor ( configStringToInt ( colorsAndAngles [ 0 ] ) . value_or ( 0 ) ) ) , priority ) ;
m_sWindowData . inactiveBorderColor = CWindowOverridableVar ( CGradientValueData ( CHyprColor ( configStringToInt ( colorsAndAngles [ 1 ] ) . value_or ( 0 ) ) ) , priority ) ;
return ;
}
2024-01-14 12:27:32 -05:00
2024-12-16 19:05:24 +01:00
for ( auto const & token : colorsAndAngles ) {
// The first angle, or an explicit "0deg", splits the two gradients
if ( active & & token . contains ( " deg " ) ) {
activeBorderGradient . m_fAngle = std : : stoi ( token . substr ( 0 , token . size ( ) - 3 ) ) * ( PI / 180.0 ) ;
active = false ;
} else if ( token . contains ( " deg " ) )
inactiveBorderGradient . m_fAngle = std : : stoi ( token . substr ( 0 , token . size ( ) - 3 ) ) * ( PI / 180.0 ) ;
else if ( active )
activeBorderGradient . m_vColors . push_back ( configStringToInt ( token ) . value_or ( 0 ) ) ;
else
inactiveBorderGradient . m_vColors . push_back ( configStringToInt ( token ) . value_or ( 0 ) ) ;
}
2024-01-14 12:27:32 -05:00
2024-12-16 19:05:24 +01:00
activeBorderGradient . updateColorsOk ( ) ;
// Includes sanity checks for the number of colors in each gradient
if ( activeBorderGradient . m_vColors . size ( ) > 10 | | inactiveBorderGradient . m_vColors . size ( ) > 10 )
Debug : : log ( WARN , " Bordercolor rule \" {} \" has more than 10 colors in one gradient, ignoring " , r - > szRule ) ;
else if ( activeBorderGradient . m_vColors . empty ( ) )
Debug : : log ( WARN , " Bordercolor rule \" {} \" has no colors, ignoring " , r - > szRule ) ;
else if ( inactiveBorderGradient . m_vColors . empty ( ) )
m_sWindowData . activeBorderColor = CWindowOverridableVar ( activeBorderGradient , priority ) ;
else {
m_sWindowData . activeBorderColor = CWindowOverridableVar ( activeBorderGradient , priority ) ;
m_sWindowData . inactiveBorderColor = CWindowOverridableVar ( inactiveBorderGradient , priority ) ;
}
} catch ( std : : exception & e ) { Debug : : log ( ERR , " BorderColor rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
break ;
2024-07-11 14:10:42 +00:00
}
2024-12-16 19:05:24 +01:00
case CWindowRule : : RULE_IDLEINHIBIT : {
auto IDLERULE = r - > szRule . substr ( r - > szRule . find_first_of ( ' ' ) + 1 ) ;
if ( IDLERULE = = " none " )
m_eIdleInhibitMode = IDLEINHIBIT_NONE ;
else if ( IDLERULE = = " always " )
m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS ;
else if ( IDLERULE = = " focus " )
m_eIdleInhibitMode = IDLEINHIBIT_FOCUS ;
else if ( IDLERULE = = " fullscreen " )
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN ;
else
Debug : : log ( ERR , " Rule idleinhibit: unknown mode {} " , IDLERULE ) ;
break ;
}
case CWindowRule : : RULE_MAXSIZE : {
try {
if ( ! m_bIsFloating )
return ;
const auto VEC = configStringToVector2D ( r - > szRule . substr ( 8 ) ) ;
if ( VEC . x < 1 | | VEC . y < 1 ) {
Debug : : log ( ERR , " Invalid size for maxsize " ) ;
return ;
}
2024-03-08 17:10:38 +00:00
2024-12-16 19:05:24 +01:00
m_sWindowData . maxSize = CWindowOverridableVar ( VEC , priority ) ;
clampWindowSize ( std : : nullopt , m_sWindowData . maxSize . value ( ) ) ;
2024-10-07 18:52:49 +00:00
2024-12-16 19:05:24 +01:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " maxsize rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
break ;
}
case CWindowRule : : RULE_MINSIZE : {
try {
if ( ! m_bIsFloating )
return ;
const auto VEC = configStringToVector2D ( r - > szRule . substr ( 8 ) ) ;
if ( VEC . x < 1 | | VEC . y < 1 ) {
Debug : : log ( ERR , " Invalid size for minsize " ) ;
return ;
}
2024-03-08 17:10:38 +00:00
2024-12-16 19:05:24 +01:00
m_sWindowData . minSize = CWindowOverridableVar ( VEC , priority ) ;
clampWindowSize ( m_sWindowData . minSize . value ( ) , std : : nullopt ) ;
2024-10-07 18:52:49 +00:00
2024-12-16 19:05:24 +01:00
if ( m_sGroupData . pNextWindow . expired ( ) )
setHidden ( false ) ;
} catch ( std : : exception & e ) { Debug : : log ( ERR , " minsize rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
break ;
}
case CWindowRule : : RULE_RENDERUNFOCUSED : {
m_sWindowData . renderUnfocused = CWindowOverridableVar ( true , priority ) ;
g_pHyprRenderer - > addWindowToRenderUnfocused ( m_pSelf . lock ( ) ) ;
break ;
}
case CWindowRule : : RULE_PROP : {
const CVarList VARS ( r - > szRule , 0 , ' ' ) ;
2025-03-02 02:13:31 +00:00
if ( auto search = NWindowProperties : : intWindowProperties . find ( VARS [ 1 ] ) ; search ! = NWindowProperties : : intWindowProperties . end ( ) ) {
2024-12-16 19:05:24 +01:00
try {
* ( search - > second ( m_pSelf . lock ( ) ) ) = CWindowOverridableVar ( std : : stoi ( VARS [ 2 ] ) , priority ) ;
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
2025-03-02 02:13:31 +00:00
} else if ( auto search = NWindowProperties : : floatWindowProperties . find ( VARS [ 1 ] ) ; search ! = NWindowProperties : : floatWindowProperties . end ( ) ) {
2024-12-16 19:05:24 +01:00
try {
* ( search - > second ( m_pSelf . lock ( ) ) ) = CWindowOverridableVar ( std : : stof ( VARS [ 2 ] ) , priority ) ;
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
2025-03-02 02:13:31 +00:00
} else if ( auto search = NWindowProperties : : boolWindowProperties . find ( VARS [ 1 ] ) ; search ! = NWindowProperties : : boolWindowProperties . end ( ) ) {
2024-12-16 19:05:24 +01:00
try {
2024-12-16 18:44:19 +00:00
* ( search - > second ( m_pSelf . lock ( ) ) ) = CWindowOverridableVar ( VARS [ 2 ] . empty ( ) ? true : ( bool ) std : : stoi ( VARS [ 2 ] ) , priority ) ;
2024-12-16 19:05:24 +01:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" {} \" failed with: {} " , r - > szRule , e . what ( ) ) ; }
}
break ;
}
2025-03-07 20:12:02 -05:00
case CWindowRule : : RULE_PERSISTENTSIZE : {
m_sWindowData . persistentSize = CWindowOverridableVar ( true , PRIORITY_WINDOW_RULE ) ;
break ;
}
2024-12-16 19:05:24 +01:00
default : break ;
2022-11-15 11:21:26 +01:00
}
}
void CWindow : : updateDynamicRules ( ) {
2024-07-11 14:10:42 +00:00
m_sWindowData . alpha . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . alphaInactive . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . alphaFullscreen . unset ( PRIORITY_WINDOW_RULE ) ;
unsetWindowData ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . animationStyle . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . maxSize . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . minSize . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . activeBorderColor . unset ( PRIORITY_WINDOW_RULE ) ;
m_sWindowData . inactiveBorderColor . unset ( PRIORITY_WINDOW_RULE ) ;
2024-08-30 17:37:52 +02:00
m_sWindowData . renderUnfocused . unset ( PRIORITY_WINDOW_RULE ) ;
2024-07-11 14:10:42 +00:00
m_eIdleInhibitMode = IDLEINHIBIT_NONE ;
2022-11-15 11:21:26 +01:00
2024-05-29 05:37:24 +08:00
m_tags . removeDynamicTags ( ) ;
2024-05-02 02:17:55 +01:00
m_vMatchedRules = g_pConfigManager - > getMatchingRules ( m_pSelf . lock ( ) ) ;
2024-12-16 19:05:24 +01:00
for ( const auto & r : m_vMatchedRules ) {
2022-11-15 11:21:26 +01:00
applyDynamicRule ( r ) ;
}
2023-07-18 00:11:43 +02:00
2024-05-02 02:17:55 +01:00
EMIT_HOOK_EVENT ( " windowUpdateRules " , m_pSelf . lock ( ) ) ;
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
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 ) {
2025-01-05 12:38:49 -06:00
const int ROUNDING = rounding ( ) ;
const int ROUNDINGPOWER = roundingPower ( ) ;
2023-08-17 08:13:19 +00:00
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
2025-01-07 17:55:14 +00:00
double x0 = m_vRealPosition - > value ( ) . x + ROUNDING ;
double y0 = m_vRealPosition - > value ( ) . y + ROUNDING ;
double x1 = m_vRealPosition - > value ( ) . x + m_vRealSize - > value ( ) . x - ROUNDING ;
double y1 = m_vRealPosition - > value ( ) . y + m_vRealSize - > value ( ) . y - ROUNDING ;
2023-02-18 23:35:31 +01:00
if ( x < x0 & & y < y0 ) {
2025-01-05 12:38:49 -06:00
return std : : pow ( x0 - x , ROUNDINGPOWER ) + std : : pow ( y0 - y , ROUNDINGPOWER ) > std : : pow ( ( double ) ROUNDING , ROUNDINGPOWER ) ;
2023-02-18 23:35:31 +01:00
}
if ( x > x1 & & y < y0 ) {
2025-01-05 12:38:49 -06:00
return std : : pow ( x - x1 , ROUNDINGPOWER ) + std : : pow ( y0 - y , ROUNDINGPOWER ) > std : : pow ( ( double ) ROUNDING , ROUNDINGPOWER ) ;
2023-02-18 23:35:31 +01:00
}
if ( x < x0 & & y > y1 ) {
2025-01-05 12:38:49 -06:00
return std : : pow ( x0 - x , ROUNDINGPOWER ) + std : : pow ( y - y1 , ROUNDINGPOWER ) > std : : pow ( ( double ) ROUNDING , ROUNDINGPOWER ) ;
2023-02-18 23:35:31 +01:00
}
if ( x > x1 & & y > y1 ) {
2025-01-05 12:38:49 -06:00
return std : : pow ( x - x1 , ROUNDINGPOWER ) + std : : pow ( y - y1 , ROUNDINGPOWER ) > std : : pow ( ( double ) ROUNDING , ROUNDINGPOWER ) ;
2023-02-18 23:35:31 +01:00
}
return false ;
}
// checks if the wayland window has a popup at pos
bool CWindow : : hasPopupAt ( const Vector2D & pos ) {
if ( m_bIsX11 )
return false ;
2025-01-26 12:54:32 +00:00
auto popup = m_pPopupHead - > at ( pos ) ;
2023-02-18 23:35:31 +01:00
2024-06-08 10:07:59 +02:00
return popup & & popup - > m_pWLSurface - > resource ( ) ;
2023-02-18 23:35:31 +01:00
}
2023-02-19 21:07:32 +00:00
2023-09-21 23:42:00 +00:00
void CWindow : : applyGroupRules ( ) {
if ( ( m_eGroupRules & GROUP_SET & & m_bFirstMap ) | | m_eGroupRules & GROUP_SET_ALWAYS )
createGroup ( ) ;
2024-04-27 12:43:12 +01:00
if ( m_sGroupData . pNextWindow . lock ( ) & & ( ( m_eGroupRules & GROUP_LOCK & & m_bFirstMap ) | | m_eGroupRules & GROUP_LOCK_ALWAYS ) )
2023-09-21 23:42:00 +00:00
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 ;
}
2023-11-11 14:37:17 +00:00
2024-04-27 12:43:12 +01:00
if ( m_sGroupData . pNextWindow . expired ( ) ) {
m_sGroupData . pNextWindow = m_pSelf ;
2023-09-21 23:42:00 +00:00
m_sGroupData . head = true ;
m_sGroupData . locked = false ;
m_sGroupData . deny = false ;
2025-01-23 21:55:41 +01:00
addWindowDeco ( makeUnique < CHyprGroupBarDecoration > ( m_pSelf . lock ( ) ) ) ;
2023-09-21 23:42:00 +00:00
2024-11-22 16:01:02 +00:00
if ( m_pWorkspace ) {
m_pWorkspace - > updateWindows ( ) ;
m_pWorkspace - > updateWindowData ( ) ;
}
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
2023-09-21 23:42:00 +00:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2024-05-07 15:00:55 +04:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " togglegroup " , std : : format ( " 1,{:x} " , ( uintptr_t ) this ) } ) ;
2023-09-21 23:42:00 +00:00
}
}
void CWindow : : destroyGroup ( ) {
2025-03-02 02:19:35 +00:00
if ( m_sGroupData . pNextWindow = = m_pSelf ) {
2023-09-21 23:42:00 +00:00
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 ;
}
2024-04-27 12:43:12 +01:00
m_sGroupData . pNextWindow . reset ( ) ;
m_sGroupData . head = false ;
2023-09-21 23:42:00 +00:00
updateWindowDecos ( ) ;
2024-11-22 16:01:02 +00:00
if ( m_pWorkspace ) {
m_pWorkspace - > updateWindows ( ) ;
m_pWorkspace - > updateWindowData ( ) ;
}
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
2024-04-11 01:26:11 +09:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2024-05-07 15:00:55 +04:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " togglegroup " , std : : format ( " 0,{:x} " , ( uintptr_t ) this ) } ) ;
2023-09-21 23:42:00 +00:00
return ;
}
2024-05-07 15:00:55 +04:00
std : : string addresses ;
2024-04-27 12:43:12 +01:00
PHLWINDOW curr = m_pSelf . lock ( ) ;
std : : vector < PHLWINDOW > members ;
2023-09-21 23:42:00 +00:00
do {
2024-04-27 12:43:12 +01:00
const auto PLASTWIN = curr ;
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
PLASTWIN - > m_sGroupData . pNextWindow . reset ( ) ;
2023-09-21 23:42:00 +00:00
curr - > setHidden ( false ) ;
members . push_back ( curr ) ;
2024-05-07 15:00:55 +04:00
addresses + = std : : format ( " {:x}, " , ( uintptr_t ) curr . get ( ) ) ;
2024-04-27 12:43:12 +01:00
} while ( curr . get ( ) ! = this ) ;
2023-09-21 23:42:00 +00:00
2024-08-26 17:25:39 +02:00
for ( auto const & w : members ) {
2023-09-21 23:42:00 +00:00
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 ;
2024-08-26 20:24:30 +02:00
for ( auto const & w : members ) {
2023-09-21 23:42:00 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreated ( w ) ;
w - > updateWindowDecos ( ) ;
}
g_pKeybindManager - > m_bGroupsLocked = GROUPSLOCKEDPREV ;
2024-04-11 01:26:11 +09:00
2024-11-22 16:01:02 +00:00
if ( m_pWorkspace ) {
m_pWorkspace - > updateWindows ( ) ;
m_pWorkspace - > updateWindowData ( ) ;
}
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitorID ( ) ) ;
2024-04-11 01:26:11 +09:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2024-05-07 15:00:55 +04:00
if ( ! addresses . empty ( ) )
addresses . pop_back ( ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " togglegroup " , std : : format ( " 0,{} " , addresses ) } ) ;
2023-09-21 23:42:00 +00:00
}
2024-04-27 12:43:12 +01:00
PHLWINDOW CWindow : : getGroupHead ( ) {
PHLWINDOW curr = m_pSelf . lock ( ) ;
2023-02-19 21:07:32 +00:00
while ( ! curr - > m_sGroupData . head )
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-02-19 21:07:32 +00:00
return curr ;
}
2024-04-27 12:43:12 +01:00
PHLWINDOW CWindow : : getGroupTail ( ) {
PHLWINDOW curr = m_pSelf . lock ( ) ;
2024-05-05 17:16:00 +01:00
while ( ! curr - > m_sGroupData . pNextWindow - > m_sGroupData . head )
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-02-19 21:07:32 +00:00
return curr ;
}
2024-04-27 12:43:12 +01:00
PHLWINDOW CWindow : : getGroupCurrent ( ) {
PHLWINDOW curr = m_pSelf . lock ( ) ;
2023-02-19 21:07:32 +00:00
while ( curr - > isHidden ( ) )
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-02-19 21:07:32 +00:00
return curr ;
}
2023-08-30 15:39:22 +00:00
int CWindow : : getGroupSize ( ) {
2024-04-27 12:43:12 +01:00
int size = 1 ;
PHLWINDOW curr = m_pSelf . lock ( ) ;
2025-03-02 02:19:35 +00:00
while ( curr - > m_sGroupData . pNextWindow ! = m_pSelf ) {
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-08-30 15:39:22 +00:00
size + + ;
}
return size ;
}
2024-04-27 12:43:12 +01:00
bool CWindow : : canBeGroupedInto ( PHLWINDOW pWindow ) {
2024-09-05 18:29:33 +02:00
static auto ALLOWGROUPMERGE = CConfigValue < Hyprlang : : INT > ( " group:merge_groups_on_drag " ) ;
bool isGroup = m_sGroupData . pNextWindow ;
bool disallowDragIntoGroup = g_pInputManager - > m_bWasDraggingWindow & & isGroup & & ! bool ( * ALLOWGROUPMERGE ) ;
2024-04-27 12:43:12 +01:00
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 . lock ( ) & & getGroupHead ( ) - > m_sGroupData . locked ) ) ) // source unlocked or isn't group
& & ! m_sGroupData . deny // source is not denied entry
2024-09-05 18:29:33 +02:00
& & ! ( m_eGroupRules & GROUP_BARRED & & m_bFirstMap ) // group rule doesn't prevent adding window
& & ! disallowDragIntoGroup ; // config allows groups to be merged
2023-10-30 14:54:12 +00:00
}
2024-04-27 12:43:12 +01:00
PHLWINDOW CWindow : : getGroupWindowByIndex ( int index ) {
2023-08-30 15:39:22 +00:00
const int SIZE = getGroupSize ( ) ;
index = ( ( index % SIZE ) + SIZE ) % SIZE ;
2024-04-27 12:43:12 +01:00
PHLWINDOW curr = getGroupHead ( ) ;
2023-08-30 15:39:22 +00:00
while ( index > 0 ) {
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-08-30 15:39:22 +00:00
index - - ;
}
return curr ;
}
2024-04-27 12:43:12 +01:00
void CWindow : : setGroupCurrent ( PHLWINDOW pWindow ) {
PHLWINDOW curr = m_sGroupData . pNextWindow . lock ( ) ;
bool isMember = false ;
while ( curr . get ( ) ! = this ) {
2023-02-19 21:07:32 +00:00
if ( curr = = pWindow ) {
isMember = true ;
break ;
}
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-02-19 21:07:32 +00:00
}
2024-04-27 12:43:12 +01:00
if ( ! isMember & & pWindow . get ( ) ! = this )
2023-02-19 21:07:32 +00:00
return ;
2023-03-10 15:19:02 +00:00
const auto PCURRENT = getGroupCurrent ( ) ;
2024-07-31 17:55:52 +00:00
const bool FULLSCREEN = PCURRENT - > isFullscreen ( ) ;
2024-04-02 20:32:39 +01:00
const auto WORKSPACE = PCURRENT - > m_pWorkspace ;
2024-09-15 17:25:06 +00:00
const auto MODE = PCURRENT - > m_sFullscreenState . internal ;
2023-02-19 21:07:32 +00:00
2024-04-27 12:43:12 +01:00
const auto CURRENTISFOCUS = PCURRENT = = g_pCompositor - > m_pLastWindow . lock ( ) ;
2023-02-19 21:07:32 +00:00
2023-03-10 15:19:02 +00:00
if ( FULLSCREEN )
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( PCURRENT , FSMODE_NONE ) ;
2023-03-10 15:19:02 +00:00
2025-01-07 17:55:14 +00:00
const auto PWINDOWSIZE = PCURRENT - > m_vRealSize - > goal ( ) ;
const auto PWINDOWPOS = PCURRENT - > m_vRealPosition - > goal ( ) ;
2024-12-27 20:50:38 +05:30
2023-02-19 21:07:32 +00:00
PCURRENT - > setHidden ( true ) ;
2023-08-15 19:15:37 +02:00
pWindow - > setHidden ( false ) ; // can remove m_pLastWindow
2023-02-19 21:07:32 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > replaceWindowDataWith ( PCURRENT , pWindow ) ;
if ( PCURRENT - > m_bIsFloating ) {
2025-01-07 17:55:14 +00:00
pWindow - > m_vRealPosition - > setValueAndWarp ( PWINDOWPOS ) ;
pWindow - > m_vRealSize - > setValueAndWarp ( PWINDOWSIZE ) ;
2023-02-19 21:07:32 +00:00
}
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
if ( CURRENTISFOCUS )
g_pCompositor - > focusWindow ( pWindow ) ;
2023-03-10 15:19:02 +00:00
if ( FULLSCREEN )
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( pWindow , MODE ) ;
2023-06-14 19:44:51 +02:00
g_pHyprRenderer - > damageWindow ( pWindow ) ;
2023-11-11 14:37:17 +00:00
pWindow - > updateWindowDecos ( ) ;
2023-02-19 21:07:32 +00:00
}
2024-04-27 12:43:12 +01:00
void CWindow : : insertWindowToGroup ( PHLWINDOW pWindow ) {
const auto BEGINAT = m_pSelf . lock ( ) ;
const auto ENDAT = m_sGroupData . pNextWindow . lock ( ) ;
2023-02-19 22:19:40 +00:00
2023-09-10 21:59:10 +00:00
if ( ! pWindow - > getDecorationByType ( DECORATION_GROUPBAR ) )
2025-01-23 21:55:41 +01:00
pWindow - > addWindowDeco ( makeUnique < CHyprGroupBarDecoration > ( pWindow ) ) ;
2023-09-10 21:59:10 +00:00
2024-04-27 12:43:12 +01:00
if ( ! pWindow - > m_sGroupData . pNextWindow . lock ( ) ) {
2023-07-20 17:48:32 +00:00
BEGINAT - > m_sGroupData . pNextWindow = pWindow ;
pWindow - > m_sGroupData . pNextWindow = ENDAT ;
pWindow - > m_sGroupData . head = false ;
2023-02-19 22:19:40 +00:00
return ;
}
2023-07-20 17:48:32 +00: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 16:30:29 +00:00
}
2024-04-27 12:43:12 +01:00
PHLWINDOW CWindow : : getGroupPrevious ( ) {
PHLWINDOW curr = m_sGroupData . pNextWindow . lock ( ) ;
2023-07-13 17:55:20 +02:00
2025-03-02 02:19:35 +00:00
while ( curr ! = m_pSelf & & curr - > m_sGroupData . pNextWindow ! = m_pSelf )
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-07-13 17:55:20 +02:00
return curr ;
}
2024-04-27 12:43:12 +01:00
void CWindow : : switchWithWindowInGroup ( PHLWINDOW pWindow ) {
if ( ! m_sGroupData . pNextWindow . lock ( ) | | ! pWindow - > m_sGroupData . pNextWindow . lock ( ) )
2023-07-13 17:55:20 +02:00
return ;
2024-04-27 12:43:12 +01:00
if ( m_sGroupData . pNextWindow . lock ( ) = = pWindow ) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
2023-07-20 17:48:32 +00:00
getGroupPrevious ( ) - > m_sGroupData . pNextWindow = pWindow ;
m_sGroupData . pNextWindow = pWindow - > m_sGroupData . pNextWindow ;
2024-04-27 12:43:12 +01:00
pWindow - > m_sGroupData . pNextWindow = m_pSelf ;
2023-07-13 17:55:20 +02:00
2025-03-02 02:19:35 +00:00
} else if ( pWindow - > m_sGroupData . pNextWindow = = m_pSelf ) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
2024-04-27 12:43:12 +01:00
pWindow - > getGroupPrevious ( ) - > m_sGroupData . pNextWindow = m_pSelf ;
2023-07-20 17:48:32 +00:00
pWindow - > m_sGroupData . pNextWindow = m_sGroupData . pNextWindow ;
m_sGroupData . pNextWindow = pWindow ;
2023-07-13 17:55:20 +02:00
2023-07-20 17:48:32 +00: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 17:48:32 +00:00
std : : swap ( m_sGroupData . locked , pWindow - > m_sGroupData . locked ) ;
2023-07-13 17:55:20 +02:00
}
2023-03-18 16:30:29 +00:00
void CWindow : : updateGroupOutputs ( ) {
2024-04-27 12:43:12 +01:00
if ( m_sGroupData . pNextWindow . expired ( ) )
2023-03-18 16:30:29 +00:00
return ;
2024-04-27 12:43:12 +01:00
PHLWINDOW curr = m_sGroupData . pNextWindow . lock ( ) ;
2024-04-02 20:32:39 +01:00
const auto WS = m_pWorkspace ;
2023-03-18 16:30:29 +00:00
2024-04-27 12:43:12 +01:00
while ( curr . get ( ) ! = this ) {
2024-10-27 18:45:38 +00:00
curr - > m_pMonitor = m_pMonitor ;
2024-04-02 20:32:39 +01:00
curr - > moveToWorkspace ( WS ) ;
2023-03-18 16:30:29 +00:00
2025-01-07 17:55:14 +00:00
* curr - > m_vRealPosition = m_vRealPosition - > goal ( ) ;
* curr - > m_vRealSize = m_vRealSize - > goal ( ) ;
2023-03-18 16:30:29 +00:00
2024-04-27 12:43:12 +01:00
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-03-18 16:30:29 +00:00
}
2023-04-14 15:03:53 +01:00
}
Vector2D CWindow : : middle ( ) {
2025-01-07 17:55:14 +00:00
return m_vRealPosition - > goal ( ) + m_vRealSize - > goal ( ) / 2.f ;
2023-04-14 15:03:53 +01:00
}
2023-04-22 12:36:50 +01:00
bool CWindow : : opaque ( ) {
2025-01-07 17:55:14 +00:00
if ( m_fAlpha - > value ( ) ! = 1.f | | m_fActiveInactiveAlpha - > value ( ) ! = 1.f )
2023-07-19 16:13:55 +02:00
return false ;
2024-04-02 20:32:39 +01:00
const auto PWORKSPACE = m_pWorkspace ;
2023-07-19 16:13:55 +02:00
2024-06-08 10:07:59 +02:00
if ( m_pWLSurface - > small ( ) & & ! m_pWLSurface - > m_bFillIgnoreSmall )
2023-10-20 20:15:41 +01:00
return false ;
2025-01-07 17:55:14 +00:00
if ( PWORKSPACE - > m_fAlpha - > value ( ) ! = 1.f )
2023-07-19 16:13:55 +02:00
return false ;
2024-07-31 20:47:26 +01:00
if ( m_bIsX11 & & m_pXWaylandSurface & & m_pXWaylandSurface - > surface & & m_pXWaylandSurface - > surface - > current . texture )
return m_pXWaylandSurface - > surface - > current . texture - > m_bOpaque ;
2023-04-22 12:36:50 +01:00
2024-07-31 20:47:26 +01:00
if ( ! m_pWLSurface - > resource ( ) | | ! m_pWLSurface - > resource ( ) - > current . texture )
2024-06-08 10:07:59 +02:00
return false ;
2023-04-22 12:36:50 +01:00
2024-06-08 10:07:59 +02:00
// TODO: this is wrong
const auto EXTENTS = m_pXDGSurface - > surface - > current . opaque . getExtents ( ) ;
2024-07-31 20:47:26 +01:00
if ( EXTENTS . w > = m_pXDGSurface - > surface - > current . bufferSize . x & & EXTENTS . h > = m_pXDGSurface - > surface - > current . bufferSize . y )
2023-04-22 12:36:50 +01:00
return true ;
2024-07-31 20:47:26 +01:00
return m_pWLSurface - > resource ( ) - > current . texture - > m_bOpaque ;
2023-04-22 12:36:50 +01:00
}
2023-07-19 16:13:55 +02:00
float CWindow : : rounding ( ) {
2025-01-05 12:38:49 -06:00
static auto PROUNDING = CConfigValue < Hyprlang : : INT > ( " decoration:rounding " ) ;
static auto PROUNDINGPOWER = CConfigValue < Hyprlang : : FLOAT > ( " decoration:rounding_power " ) ;
2023-07-19 16:13:55 +02:00
2025-01-05 12:38:49 -06:00
float roundingPower = m_sWindowData . roundingPower . valueOr ( * PROUNDINGPOWER ) ;
float rounding = m_sWindowData . rounding . valueOr ( * PROUNDING ) * ( roundingPower / 2.0 ) ; /* Make perceived roundness consistent. */
2023-07-19 16:13:55 +02:00
2024-07-11 14:10:42 +00:00
return m_sWindowData . noRounding . valueOrDefault ( ) ? 0 : rounding ;
2023-07-19 16:13:55 +02:00
}
2023-08-17 08:13:19 +00:00
2025-01-05 12:38:49 -06:00
float CWindow : : roundingPower ( ) {
static auto PROUNDINGPOWER = CConfigValue < Hyprlang : : FLOAT > ( " decoration:rounding_power " ) ;
return m_sWindowData . roundingPower . valueOr ( * PROUNDINGPOWER ) ;
}
2024-07-11 14:10:42 +00:00
void CWindow : : updateWindowData ( ) {
2024-04-11 01:26:11 +09:00
const auto PWORKSPACE = m_pWorkspace ;
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager - > getWorkspaceRuleFor ( PWORKSPACE ) : SWorkspaceRule { } ;
2024-07-11 14:10:42 +00:00
updateWindowData ( WORKSPACERULE ) ;
2024-04-11 01:26:11 +09:00
}
2023-08-17 08:13:19 +00:00
2024-07-11 14:10:42 +00:00
void CWindow : : updateWindowData ( const SWorkspaceRule & workspaceRule ) {
2024-03-03 18:39:20 +00:00
static auto PNOBORDERONFLOATING = CConfigValue < Hyprlang : : INT > ( " general:no_border_on_floating " ) ;
2024-02-18 15:00:34 +00:00
2024-07-11 14:10:42 +00:00
if ( * PNOBORDERONFLOATING )
m_sWindowData . noBorder = CWindowOverridableVar ( m_bIsFloating , PRIORITY_LAYOUT ) ;
else
m_sWindowData . noBorder . unset ( PRIORITY_LAYOUT ) ;
2023-08-17 08:13:19 +00:00
2024-07-11 14:10:42 +00:00
m_sWindowData . borderSize . matchOptional ( workspaceRule . borderSize , PRIORITY_WORKSPACE_RULE ) ;
m_sWindowData . decorate . matchOptional ( workspaceRule . decorate , PRIORITY_WORKSPACE_RULE ) ;
m_sWindowData . noBorder . matchOptional ( workspaceRule . noBorder , PRIORITY_WORKSPACE_RULE ) ;
m_sWindowData . noRounding . matchOptional ( workspaceRule . noRounding , PRIORITY_WORKSPACE_RULE ) ;
m_sWindowData . noShadow . matchOptional ( workspaceRule . noShadow , PRIORITY_WORKSPACE_RULE ) ;
2023-08-17 08:13:19 +00:00
}
int CWindow : : getRealBorderSize ( ) {
2024-07-31 17:55:52 +00:00
if ( m_sWindowData . noBorder . valueOrDefault ( ) | | ( m_pWorkspace & & isEffectiveInternalFSMode ( FSMODE_FULLSCREEN ) ) )
2023-08-17 08:13:19 +00:00
return 0 ;
2024-03-03 18:39:20 +00:00
static auto PBORDERSIZE = CConfigValue < Hyprlang : : INT > ( " general:border_size " ) ;
2024-02-18 15:00:34 +00:00
2024-07-11 14:10:42 +00:00
return m_sWindowData . borderSize . valueOr ( * PBORDERSIZE ) ;
2023-08-17 08:13:19 +00:00
}
2023-09-28 21:48:33 +01:00
2024-12-06 01:16:58 -05:00
float CWindow : : getScrollMouse ( ) {
static auto PINPUTSCROLLFACTOR = CConfigValue < Hyprlang : : FLOAT > ( " input:scroll_factor " ) ;
return m_sWindowData . scrollMouse . valueOr ( * PINPUTSCROLLFACTOR ) ;
}
float CWindow : : getScrollTouchpad ( ) {
static auto PTOUCHPADSCROLLFACTOR = CConfigValue < Hyprlang : : FLOAT > ( " input:touchpad:scroll_factor " ) ;
return m_sWindowData . scrollTouchpad . valueOr ( * PTOUCHPADSCROLLFACTOR ) ;
}
2023-09-28 21:48:33 +01:00
bool CWindow : : canBeTorn ( ) {
2024-07-21 13:09:54 +02:00
static auto PTEARING = CConfigValue < Hyprlang : : INT > ( " general:allow_tearing " ) ;
return m_sWindowData . tearing . valueOr ( m_bTearingHint ) & & * PTEARING ;
2023-09-28 21:48:33 +01:00
}
2023-12-11 17:51:10 +01:00
2023-12-23 22:30:49 +01:00
void CWindow : : setSuspended ( bool suspend ) {
if ( suspend = = m_bSuspended )
return ;
2025-04-08 13:43:15 -04:00
if ( m_bIsX11 | | ! m_pXDGSurface | | ! m_pXDGSurface - > toplevel )
2023-12-23 22:30:49 +01:00
return ;
2024-05-10 23:28:33 +01:00
m_pXDGSurface - > toplevel - > setSuspeneded ( suspend ) ;
2023-12-29 00:26:23 +01:00
m_bSuspended = suspend ;
2023-12-23 22:30:49 +01:00
}
2024-03-14 18:25:28 +00:00
2024-10-19 23:03:29 +01:00
bool CWindow : : visibleOnMonitor ( PHLMONITOR pMonitor ) {
2025-01-07 17:55:14 +00:00
CBox wbox = { m_vRealPosition - > value ( ) , m_vRealSize - > value ( ) } ;
2024-03-14 18:25:28 +00:00
2024-05-05 22:18:10 +01:00
return ! wbox . intersection ( { pMonitor - > vecPosition , pMonitor - > vecSize } ) . empty ( ) ;
2024-03-14 18:25:28 +00:00
}
2024-03-18 19:52:52 -07:00
void CWindow : : setAnimationsToMove ( ) {
2025-01-07 17:55:14 +00:00
m_vRealPosition - > setConfig ( g_pConfigManager - > getAnimationPropertyConfig ( " windowsMove " ) ) ;
2024-03-18 19:52:52 -07:00
m_bAnimatingIn = false ;
}
2024-03-25 16:08:55 +00:00
2024-03-30 18:14:26 -07:00
void CWindow : : onWorkspaceAnimUpdate ( ) {
// clip box for animated offsets
2025-03-15 19:15:09 +01:00
if ( ! m_bIsFloating | | m_bPinned | | isFullscreen ( ) | | m_bDraggingTiled ) {
2024-03-30 18:14:26 -07:00
m_vFloatingOffset = Vector2D ( 0 , 0 ) ;
return ;
}
Vector2D offset ;
2024-04-02 20:32:39 +01:00
const auto PWORKSPACE = m_pWorkspace ;
2024-03-30 18:14:26 -07:00
if ( ! PWORKSPACE )
return ;
2024-10-27 18:45:38 +00:00
const auto PWSMON = m_pMonitor . lock ( ) ;
2024-03-30 18:14:26 -07:00
if ( ! PWSMON )
return ;
const auto WINBB = getFullWindowBoundingBox ( ) ;
2025-01-07 17:55:14 +00:00
if ( PWORKSPACE - > m_vRenderOffset - > value ( ) . x ! = 0 ) {
const auto PROGRESS = PWORKSPACE - > m_vRenderOffset - > value ( ) . x / PWSMON - > vecSize . x ;
2024-03-30 18:14:26 -07:00
if ( WINBB . x < PWSMON - > vecPosition . x )
offset . x + = ( PWSMON - > vecPosition . x - WINBB . x ) * PROGRESS ;
if ( WINBB . x + WINBB . width > PWSMON - > vecPosition . x + PWSMON - > vecSize . x )
offset . x + = ( WINBB . x + WINBB . width - PWSMON - > vecPosition . x - PWSMON - > vecSize . x ) * PROGRESS ;
2025-01-07 17:55:14 +00:00
} else if ( PWORKSPACE - > m_vRenderOffset - > value ( ) . y ! = 0 ) {
const auto PROGRESS = PWORKSPACE - > m_vRenderOffset - > value ( ) . y / PWSMON - > vecSize . y ;
2024-03-30 18:14:26 -07:00
if ( WINBB . y < PWSMON - > vecPosition . y )
offset . y + = ( PWSMON - > vecPosition . y - WINBB . y ) * PROGRESS ;
if ( WINBB . y + WINBB . height > PWSMON - > vecPosition . y + PWSMON - > vecSize . y )
offset . y + = ( WINBB . y + WINBB . height - PWSMON - > vecPosition . y - PWSMON - > vecSize . y ) * PROGRESS ;
}
m_vFloatingOffset = offset ;
}
2025-01-24 18:22:05 +00:00
void CWindow : : onFocusAnimUpdate ( ) {
// borderangle once
if ( m_fBorderAngleAnimationProgress - > enabled ( ) & & ! m_fBorderAngleAnimationProgress - > isBeingAnimated ( ) ) {
m_fBorderAngleAnimationProgress - > setValueAndWarp ( 0.f ) ;
* m_fBorderAngleAnimationProgress = 1.f ;
}
}
2024-03-25 16:08:55 +00:00
int CWindow : : popupsCount ( ) {
2024-05-10 23:28:33 +01:00
if ( m_bIsX11 )
return 0 ;
int no = - 1 ;
2025-01-26 12:54:32 +00:00
m_pPopupHead - > breadthfirst ( [ ] ( WP < CPopup > p , void * d ) { * ( ( int * ) d ) + = 1 ; } , & no ) ;
2024-05-10 23:28:33 +01:00
return no ;
}
int CWindow : : surfacesCount ( ) {
2024-03-25 16:08:55 +00:00
if ( m_bIsX11 )
return 1 ;
int no = 0 ;
2024-06-08 10:07:59 +02:00
m_pWLSurface - > resource ( ) - > breadthfirst ( [ ] ( SP < CWLSurfaceResource > r , const Vector2D & offset , void * d ) { * ( ( int * ) d ) + = 1 ; } , & no ) ;
2024-03-25 16:08:55 +00:00
return no ;
}
2024-04-02 20:32:39 +01:00
2024-10-07 18:52:49 +00:00
void CWindow : : clampWindowSize ( const std : : optional < Vector2D > minSize , const std : : optional < Vector2D > maxSize ) {
2025-01-07 17:55:14 +00:00
const Vector2D REALSIZE = m_vRealSize - > goal ( ) ;
2024-10-30 18:58:36 +00:00
const Vector2D NEWSIZE = REALSIZE . clamp ( minSize . value_or ( Vector2D { MIN_WINDOW_SIZE , MIN_WINDOW_SIZE } ) , maxSize . value_or ( Vector2D { INFINITY , INFINITY } ) ) ;
2024-10-07 18:52:49 +00:00
const Vector2D DELTA = REALSIZE - NEWSIZE ;
2025-01-07 17:55:14 +00:00
* m_vRealPosition = m_vRealPosition - > goal ( ) + DELTA / 2.0 ;
* m_vRealSize = NEWSIZE ;
2024-10-07 18:52:49 +00:00
}
2024-07-31 17:55:52 +00:00
bool CWindow : : isFullscreen ( ) {
return m_sFullscreenState . internal ! = FSMODE_NONE ;
}
bool CWindow : : isEffectiveInternalFSMode ( const eFullscreenMode MODE ) {
return ( eFullscreenMode ) std : : bit_floor ( ( uint8_t ) m_sFullscreenState . internal ) = = MODE ;
}
2024-08-08 21:01:50 +02:00
WORKSPACEID CWindow : : workspaceID ( ) {
2024-04-02 20:32:39 +01:00
return m_pWorkspace ? m_pWorkspace - > m_iID : m_iLastWorkspace ;
}
2024-10-27 18:45:38 +00:00
MONITORID CWindow : : monitorID ( ) {
return m_pMonitor ? m_pMonitor - > ID : MONITOR_INVALID ;
}
2024-04-02 20:32:39 +01:00
bool CWindow : : onSpecialWorkspace ( ) {
return m_pWorkspace ? m_pWorkspace - > m_bIsSpecialWorkspace : g_pCompositor - > isWorkspaceSpecial ( m_iLastWorkspace ) ;
}
2024-04-23 01:28:20 +01:00
std : : unordered_map < std : : string , std : : string > CWindow : : getEnv ( ) {
const auto PID = getPID ( ) ;
if ( PID < = 1 )
return { } ;
std : : unordered_map < std : : string , std : : string > results ;
//
2024-04-23 00:40:03 +00:00
std : : string environFile = " /proc/ " + std : : to_string ( PID ) + " /environ " ;
std : : ifstream ifs ( environFile , std : : ios : : binary ) ;
2024-04-23 01:28:20 +01:00
if ( ! ifs . good ( ) )
return { } ;
std : : vector < char > buffer ;
size_t needle = 0 ;
buffer . resize ( 512 , ' \0 ' ) ;
while ( ifs . read ( buffer . data ( ) + needle , 512 ) ) {
buffer . resize ( buffer . size ( ) + 512 , ' \0 ' ) ;
needle + = 512 ;
}
2024-05-24 20:40:15 +02:00
if ( needle < = 1 )
return { } ;
2024-04-23 01:28:20 +01:00
std : : replace ( buffer . begin ( ) , buffer . end ( ) - 1 , ' \0 ' , ' \n ' ) ;
2024-05-24 20:40:15 +02:00
CVarList envs ( std : : string { buffer . data ( ) , buffer . size ( ) - 1 } , 0 , ' \n ' , true ) ;
2024-04-23 01:28:20 +01:00
2024-08-26 20:24:30 +02:00
for ( auto const & e : envs ) {
2024-04-23 01:28:20 +01:00
if ( ! e . contains ( ' = ' ) )
continue ;
const auto EQ = e . find_first_of ( ' = ' ) ;
results [ e . substr ( 0 , EQ ) ] = e . substr ( EQ + 1 ) ;
}
return results ;
}
2024-04-25 00:58:40 +01:00
2024-05-08 01:31:16 +01:00
void CWindow : : activate ( bool force ) {
2024-05-10 23:28:33 +01:00
if ( g_pCompositor - > m_pLastWindow = = m_pSelf )
return ;
2024-04-25 00:58:40 +01:00
static auto PFOCUSONACTIVATE = CConfigValue < Hyprlang : : INT > ( " misc:focus_on_activate " ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " urgent " , std : : format ( " {:x} " , ( uintptr_t ) this ) } ) ;
2024-04-27 12:43:12 +01:00
EMIT_HOOK_EVENT ( " urgent " , m_pSelf . lock ( ) ) ;
2024-04-25 00:58:40 +01:00
m_bIsUrgent = true ;
2024-07-11 14:10:42 +00:00
if ( ! force & & ( ! m_sWindowData . focusOnActivate . valueOr ( * PFOCUSONACTIVATE ) | | ( m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY ) | | ( m_eSuppressedEvents & SUPPRESS_ACTIVATE ) ) )
2024-04-25 00:58:40 +01:00
return ;
2024-08-28 20:33:29 +02:00
if ( ! m_bIsMapped ) {
Debug : : log ( LOG , " Ignoring CWindow::activate focus/warp, window is not mapped yet. " ) ;
return ;
}
2024-04-25 00:58:40 +01:00
if ( m_bIsFloating )
2024-04-27 12:43:12 +01:00
g_pCompositor - > changeWindowZOrder ( m_pSelf . lock ( ) , true ) ;
2024-04-25 00:58:40 +01:00
2024-04-27 12:43:12 +01:00
g_pCompositor - > focusWindow ( m_pSelf . lock ( ) ) ;
2024-06-07 17:52:15 +00:00
warpCursor ( ) ;
2024-04-25 00:58:40 +01:00
}
2024-05-10 23:28:33 +01:00
void CWindow : : onUpdateState ( ) {
2025-01-09 17:38:38 -05:00
std : : optional < bool > requestsFS = m_pXDGSurface ? m_pXDGSurface - > toplevel - > state . requestsFullscreen : m_pXWaylandSurface - > state . requestsFullscreen ;
std : : optional < MONITORID > requestsID = m_pXDGSurface ? m_pXDGSurface - > toplevel - > state . requestsFullscreenMonitor : MONITOR_INVALID ;
std : : optional < bool > requestsMX = m_pXDGSurface ? m_pXDGSurface - > toplevel - > state . requestsMaximize : m_pXWaylandSurface - > state . requestsMaximize ;
2024-05-10 23:28:33 +01:00
2024-05-25 22:43:51 +02:00
if ( requestsFS . has_value ( ) & & ! ( m_eSuppressedEvents & SUPPRESS_FULLSCREEN ) ) {
2025-01-09 17:38:38 -05:00
if ( requestsID . has_value ( ) & & ( requestsID . value ( ) ! = MONITOR_INVALID ) & & ! ( m_eSuppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT ) ) {
if ( m_bIsMapped ) {
const auto monitor = g_pCompositor - > getMonitorFromID ( requestsID . value ( ) ) ;
g_pCompositor - > moveWindowToWorkspaceSafe ( m_pSelf . lock ( ) , monitor - > activeWorkspace ) ;
g_pCompositor - > setActiveMonitor ( monitor ) ;
}
if ( ! m_bIsMapped )
m_iWantsInitialFullscreenMonitor = requestsID . value ( ) ;
}
2024-05-25 22:43:51 +02:00
bool fs = requestsFS . value ( ) ;
2025-01-09 17:38:38 -05:00
if ( m_bIsMapped )
2024-07-31 17:55:52 +00:00
g_pCompositor - > changeWindowFullscreenModeClient ( m_pSelf . lock ( ) , FSMODE_FULLSCREEN , requestsFS . value ( ) ) ;
2024-05-10 23:28:33 +01:00
2024-05-25 22:43:51 +02:00
if ( ! m_bIsMapped )
2024-05-10 23:28:33 +01:00
m_bWantsInitialFullscreen = fs ;
}
2024-05-25 22:43:51 +02:00
if ( requestsMX . has_value ( ) & & ! ( m_eSuppressedEvents & SUPPRESS_MAXIMIZE ) ) {
2024-07-31 17:55:52 +00:00
if ( m_bIsMapped )
g_pCompositor - > changeWindowFullscreenModeClient ( m_pSelf . lock ( ) , FSMODE_MAXIMIZED , requestsMX . value ( ) ) ;
2024-05-10 23:28:33 +01:00
}
}
void CWindow : : onUpdateMeta ( ) {
const auto NEWTITLE = fetchTitle ( ) ;
2024-05-29 05:37:24 +08:00
bool doUpdate = false ;
2024-05-10 23:28:33 +01:00
if ( m_szTitle ! = NEWTITLE ) {
m_szTitle = NEWTITLE ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " windowtitle " , std : : format ( " {:x} " , ( uintptr_t ) this ) } ) ;
2024-07-13 07:21:32 -07:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " windowtitlev2 " , std : : format ( " {:x},{} " , ( uintptr_t ) this , m_szTitle ) } ) ;
2024-05-10 23:28:33 +01:00
EMIT_HOOK_EVENT ( " windowTitle " , m_pSelf . lock ( ) ) ;
if ( m_pSelf = = g_pCompositor - > m_pLastWindow ) { // if it's the active, let's post an event to update others
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindow " , m_szClass + " , " + m_szTitle } ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindowv2 " , std : : format ( " {:x} " , ( uintptr_t ) this ) } ) ;
EMIT_HOOK_EVENT ( " activeWindow " , m_pSelf . lock ( ) ) ;
}
Debug : : log ( LOG , " Window {:x} set title to {} " , ( uintptr_t ) this , m_szTitle ) ;
2024-05-29 05:37:24 +08:00
doUpdate = true ;
2024-05-10 23:28:33 +01:00
}
const auto NEWCLASS = fetchClass ( ) ;
if ( m_szClass ! = NEWCLASS ) {
m_szClass = NEWCLASS ;
if ( m_pSelf = = g_pCompositor - > m_pLastWindow ) { // if it's the active, let's post an event to update others
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindow " , m_szClass + " , " + m_szTitle } ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindowv2 " , std : : format ( " {:x} " , ( uintptr_t ) this ) } ) ;
EMIT_HOOK_EVENT ( " activeWindow " , m_pSelf . lock ( ) ) ;
}
2024-05-29 05:37:24 +08:00
Debug : : log ( LOG , " Window {:x} set class to {} " , ( uintptr_t ) this , m_szClass ) ;
doUpdate = true ;
}
if ( doUpdate ) {
2024-05-10 23:28:33 +01:00
updateDynamicRules ( ) ;
g_pCompositor - > updateWindowAnimatedDecorationValues ( m_pSelf . lock ( ) ) ;
updateToplevel ( ) ;
}
}
std : : string CWindow : : fetchTitle ( ) {
if ( ! m_bIsX11 ) {
if ( m_pXDGSurface & & m_pXDGSurface - > toplevel )
return m_pXDGSurface - > toplevel - > state . title ;
} else {
2024-05-25 22:43:51 +02:00
if ( m_pXWaylandSurface )
return m_pXWaylandSurface - > state . title ;
2024-05-10 23:28:33 +01:00
}
return " " ;
}
std : : string CWindow : : fetchClass ( ) {
if ( ! m_bIsX11 ) {
if ( m_pXDGSurface & & m_pXDGSurface - > toplevel )
return m_pXDGSurface - > toplevel - > state . appid ;
} else {
2024-05-25 22:43:51 +02:00
if ( m_pXWaylandSurface )
return m_pXWaylandSurface - > state . appid ;
2024-05-10 23:28:33 +01:00
}
return " " ;
}
void CWindow : : onAck ( uint32_t serial ) {
const auto SERIAL = std : : find_if ( m_vPendingSizeAcks . rbegin ( ) , m_vPendingSizeAcks . rend ( ) , [ serial ] ( const auto & e ) { return e . first = = serial ; } ) ;
if ( SERIAL = = m_vPendingSizeAcks . rend ( ) )
return ;
m_pPendingSizeAck = * SERIAL ;
std : : erase_if ( m_vPendingSizeAcks , [ & ] ( const auto & el ) { return el . first < = SERIAL - > first ; } ) ;
2024-05-25 22:43:51 +02:00
}
void CWindow : : onResourceChangeX11 ( ) {
2024-06-08 10:07:59 +02:00
if ( m_pXWaylandSurface - > surface & & ! m_pWLSurface - > resource ( ) )
m_pWLSurface - > assign ( m_pXWaylandSurface - > surface . lock ( ) , m_pSelf . lock ( ) ) ;
else if ( ! m_pXWaylandSurface - > surface & & m_pWLSurface - > resource ( ) )
m_pWLSurface - > unassign ( ) ;
2024-05-25 22:43:51 +02:00
// update metadata as well,
// could be first assoc and we need to catch the class
onUpdateMeta ( ) ;
2024-06-08 10:07:59 +02:00
Debug : : log ( LOG , " xwayland window {:x} -> association to {:x} " , ( uintptr_t ) m_pXWaylandSurface . get ( ) , ( uintptr_t ) m_pWLSurface - > resource ( ) . get ( ) ) ;
2024-05-25 22:43:51 +02:00
}
2025-02-16 00:20:42 +00:00
void CWindow : : onX11ConfigureRequest ( CBox box ) {
2024-05-25 22:43:51 +02:00
if ( ! m_pXWaylandSurface - > surface | | ! m_pXWaylandSurface - > mapped | | ! m_bIsMapped ) {
m_pXWaylandSurface - > configure ( box ) ;
m_vPendingReportedSize = box . size ( ) ;
m_vReportedSize = box . size ( ) ;
2025-02-16 00:20:42 +00:00
m_vReportedPosition = box . pos ( ) ;
updateX11SurfaceScale ( ) ;
2024-05-25 22:43:51 +02:00
return ;
}
g_pHyprRenderer - > damageWindow ( m_pSelf . lock ( ) ) ;
2024-07-31 17:55:52 +00:00
if ( ! m_bIsFloating | | isFullscreen ( ) | | g_pInputManager - > currentlyDraggedWindow = = m_pSelf ) {
2025-02-06 11:21:04 +00:00
sendWindowSize ( true ) ;
2024-05-25 22:43:51 +02:00
g_pInputManager - > refocus ( ) ;
g_pHyprRenderer - > damageWindow ( m_pSelf . lock ( ) ) ;
return ;
}
if ( box . size ( ) > Vector2D { 1 , 1 } )
setHidden ( false ) ;
else
setHidden ( true ) ;
2025-02-16 00:20:42 +00:00
m_vRealPosition - > setValueAndWarp ( xwaylandPositionToReal ( box . pos ( ) ) ) ;
m_vRealSize - > setValueAndWarp ( xwaylandSizeToReal ( box . size ( ) ) ) ;
2024-05-25 22:43:51 +02:00
2025-01-25 02:35:41 +00:00
m_vPosition = m_vRealPosition - > goal ( ) ;
m_vSize = m_vRealSize - > goal ( ) ;
2024-05-25 22:43:51 +02:00
2025-02-16 00:20:42 +00:00
if ( m_vPendingReportedSize ! = box . size ( ) | | m_vReportedPosition ! = box . pos ( ) ) {
m_pXWaylandSurface - > configure ( box ) ;
m_vReportedSize = box . size ( ) ;
m_vPendingReportedSize = box . size ( ) ;
m_vReportedPosition = box . pos ( ) ;
}
2024-05-25 22:43:51 +02:00
2025-02-16 00:20:42 +00:00
updateX11SurfaceScale ( ) ;
2024-05-25 22:43:51 +02:00
updateWindowDecos ( ) ;
2024-11-22 16:01:02 +00:00
if ( ! m_pWorkspace | | ! m_pWorkspace - > isVisible ( ) )
2024-05-25 22:43:51 +02:00
return ; // further things are only for visible windows
2025-01-25 02:35:41 +00:00
m_pWorkspace = g_pCompositor - > getMonitorFromVector ( m_vRealPosition - > goal ( ) + m_vRealSize - > goal ( ) / 2.f ) - > activeWorkspace ;
2024-05-25 22:43:51 +02:00
g_pCompositor - > changeWindowZOrder ( m_pSelf . lock ( ) , true ) ;
m_bCreatedOverFullscreen = true ;
g_pHyprRenderer - > damageWindow ( m_pSelf . lock ( ) ) ;
}
2024-06-07 17:52:15 +00:00
2024-12-10 23:55:05 +03:00
void CWindow : : warpCursor ( bool force ) {
2024-06-07 17:52:15 +00:00
static auto PERSISTENTWARPS = CConfigValue < Hyprlang : : INT > ( " cursor:persistent_warps " ) ;
const auto coords = m_vRelativeCursorCoordsOnLastWarp ;
m_vRelativeCursorCoordsOnLastWarp . x = - 1 ; // reset m_vRelativeCursorCoordsOnLastWarp
if ( * PERSISTENTWARPS & & coords . x > 0 & & coords . y > 0 & & coords < m_vSize ) // don't warp cursor outside the window
2024-12-10 23:55:05 +03:00
g_pCompositor - > warpCursorTo ( m_vPosition + coords , force ) ;
2024-06-07 17:52:15 +00:00
else
2024-12-10 23:55:05 +03:00
g_pCompositor - > warpCursorTo ( middle ( ) , force ) ;
2024-06-07 17:52:15 +00:00
}
2024-06-15 18:20:09 +02:00
PHLWINDOW CWindow : : getSwallower ( ) {
static auto PSWALLOWREGEX = CConfigValue < std : : string > ( " misc:swallow_regex " ) ;
static auto PSWALLOWEXREGEX = CConfigValue < std : : string > ( " misc:swallow_exception_regex " ) ;
static auto PSWALLOW = CConfigValue < Hyprlang : : INT > ( " misc:enable_swallow " ) ;
2024-10-28 16:52:14 +00:00
if ( ! * PSWALLOW | | std : : string { * PSWALLOWREGEX } = = STRVAL_EMPTY | | ( * PSWALLOWREGEX ) . empty ( ) )
2024-06-15 18:20:09 +02:00
return nullptr ;
// check parent
std : : vector < PHLWINDOW > candidates ;
pid_t currentPid = getPID ( ) ;
// walk up the tree until we find someone, 25 iterations max.
for ( size_t i = 0 ; i < 25 ; + + i ) {
currentPid = getPPIDof ( currentPid ) ;
if ( ! currentPid )
break ;
2024-08-26 20:24:30 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-06-15 18:20:09 +02:00
if ( ! w - > m_bIsMapped | | w - > isHidden ( ) )
continue ;
if ( w - > getPID ( ) = = currentPid )
candidates . push_back ( w ) ;
}
}
if ( ! ( * PSWALLOWREGEX ) . empty ( ) )
2024-12-16 19:21:44 +01:00
std : : erase_if ( candidates , [ & ] ( const auto & other ) { return ! RE2 : : FullMatch ( other - > m_szClass , * PSWALLOWREGEX ) ; } ) ;
2024-06-15 18:20:09 +02:00
2025-02-06 12:18:04 +01:00
if ( candidates . size ( ) = = 0 )
2024-06-15 18:20:09 +02:00
return nullptr ;
if ( ! ( * PSWALLOWEXREGEX ) . empty ( ) )
2024-12-16 19:21:44 +01:00
std : : erase_if ( candidates , [ & ] ( const auto & other ) { return RE2 : : FullMatch ( other - > m_szTitle , * PSWALLOWEXREGEX ) ; } ) ;
2024-06-15 18:20:09 +02:00
2025-02-06 12:18:04 +01:00
if ( candidates . size ( ) = = 0 )
2024-06-15 18:20:09 +02:00
return nullptr ;
if ( candidates . size ( ) = = 1 )
2025-02-06 12:18:04 +01:00
return candidates [ 0 ] ;
2024-06-15 18:20:09 +02:00
// walk up the focus history and find the last focused
2024-08-26 20:24:30 +02:00
for ( auto const & w : g_pCompositor - > m_vWindowFocusHistory ) {
2024-06-15 18:20:09 +02:00
if ( ! w )
continue ;
if ( std : : find ( candidates . begin ( ) , candidates . end ( ) , w . lock ( ) ) ! = candidates . end ( ) )
return w . lock ( ) ;
}
// if none are found (??) then just return the first one
2025-02-06 12:18:04 +01:00
return candidates [ 0 ] ;
2024-06-15 18:20:09 +02:00
}
2024-07-11 14:10:42 +00:00
void CWindow : : unsetWindowData ( eOverridePriority priority ) {
2025-03-02 02:13:31 +00:00
for ( auto const & element : NWindowProperties : : boolWindowProperties ) {
2024-07-11 14:10:42 +00:00
element . second ( m_pSelf . lock ( ) ) - > unset ( priority ) ;
}
2025-03-02 02:13:31 +00:00
for ( auto const & element : NWindowProperties : : intWindowProperties ) {
2024-07-11 14:10:42 +00:00
element . second ( m_pSelf . lock ( ) ) - > unset ( priority ) ;
}
2025-03-02 02:13:31 +00:00
for ( auto const & element : NWindowProperties : : floatWindowProperties ) {
2024-12-06 01:16:58 -05:00
element . second ( m_pSelf . lock ( ) ) - > unset ( priority ) ;
}
2024-07-11 14:10:42 +00:00
}
2024-08-30 14:12:23 +02:00
bool CWindow : : isX11OverrideRedirect ( ) {
return m_pXWaylandSurface & & m_pXWaylandSurface - > overrideRedirect ;
}
bool CWindow : : isModal ( ) {
return ( m_pXWaylandSurface & & m_pXWaylandSurface - > modal ) ;
}
2024-11-17 19:31:54 +00:00
Vector2D CWindow : : requestedMinSize ( ) {
if ( ( m_bIsX11 & & ! m_pXWaylandSurface - > sizeHints ) | | ( ! m_bIsX11 & & ! m_pXDGSurface - > toplevel ) )
return Vector2D ( 1 , 1 ) ;
Vector2D minSize = m_bIsX11 ? Vector2D ( m_pXWaylandSurface - > sizeHints - > min_width , m_pXWaylandSurface - > sizeHints - > min_height ) : m_pXDGSurface - > toplevel - > layoutMinSize ( ) ;
minSize = minSize . clamp ( { 1 , 1 } ) ;
return minSize ;
}
Vector2D CWindow : : requestedMaxSize ( ) {
constexpr int NO_MAX_SIZE_LIMIT = 99999 ;
2025-04-08 13:43:15 -04:00
if ( ( ( m_bIsX11 & & ! m_pXWaylandSurface - > sizeHints ) | | ( ! m_bIsX11 & & ( ! m_pXDGSurface | | ! m_pXDGSurface - > toplevel ) ) | | m_sWindowData . noMaxSize . valueOrDefault ( ) ) )
2024-11-17 19:31:54 +00:00
return Vector2D ( NO_MAX_SIZE_LIMIT , NO_MAX_SIZE_LIMIT ) ;
Vector2D maxSize = m_bIsX11 ? Vector2D ( m_pXWaylandSurface - > sizeHints - > max_width , m_pXWaylandSurface - > sizeHints - > max_height ) : m_pXDGSurface - > toplevel - > layoutMaxSize ( ) ;
if ( maxSize . x < 5 )
maxSize . x = NO_MAX_SIZE_LIMIT ;
if ( maxSize . y < 5 )
maxSize . y = NO_MAX_SIZE_LIMIT ;
return maxSize ;
}
2025-01-25 20:36:44 +00:00
2025-02-16 00:20:42 +00:00
Vector2D CWindow : : realToReportSize ( ) {
if ( ! m_bIsX11 )
return m_vRealSize - > goal ( ) . clamp ( Vector2D { 0 , 0 } , Vector2D { std : : numeric_limits < double > : : infinity ( ) , std : : numeric_limits < double > : : infinity ( ) } ) ;
static auto PXWLFORCESCALEZERO = CConfigValue < Hyprlang : : INT > ( " xwayland:force_zero_scaling " ) ;
const auto REPORTSIZE = m_vRealSize - > goal ( ) . clamp ( Vector2D { 1 , 1 } , Vector2D { std : : numeric_limits < double > : : infinity ( ) , std : : numeric_limits < double > : : infinity ( ) } ) ;
const auto PMONITOR = m_pMonitor . lock ( ) ;
if ( * PXWLFORCESCALEZERO & & PMONITOR )
return REPORTSIZE * PMONITOR - > scale ;
return REPORTSIZE ;
}
Vector2D CWindow : : realToReportPosition ( ) {
if ( ! m_bIsX11 )
return m_vRealPosition - > goal ( ) ;
return g_pXWaylandManager - > waylandToXWaylandCoords ( m_vRealPosition - > goal ( ) ) ;
}
Vector2D CWindow : : xwaylandSizeToReal ( Vector2D size ) {
static auto PXWLFORCESCALEZERO = CConfigValue < Hyprlang : : INT > ( " xwayland:force_zero_scaling " ) ;
const auto PMONITOR = m_pMonitor . lock ( ) ;
const auto SIZE = size . clamp ( Vector2D { 1 , 1 } , Vector2D { std : : numeric_limits < double > : : infinity ( ) , std : : numeric_limits < double > : : infinity ( ) } ) ;
const auto SCALE = * PXWLFORCESCALEZERO ? PMONITOR - > scale : 1.0f ;
return SIZE / SCALE ;
}
Vector2D CWindow : : xwaylandPositionToReal ( Vector2D pos ) {
return g_pXWaylandManager - > xwaylandToWaylandCoords ( pos ) ;
}
void CWindow : : updateX11SurfaceScale ( ) {
2025-01-25 20:36:44 +00:00
static auto PXWLFORCESCALEZERO = CConfigValue < Hyprlang : : INT > ( " xwayland:force_zero_scaling " ) ;
2025-02-16 00:20:42 +00:00
m_fX11SurfaceScaledBy = 1.0f ;
if ( m_bIsX11 & & * PXWLFORCESCALEZERO ) {
if ( const auto PMONITOR = m_pMonitor . lock ( ) ; PMONITOR )
m_fX11SurfaceScaledBy = PMONITOR - > scale ;
}
}
void CWindow : : sendWindowSize ( bool force ) {
const auto PMONITOR = m_pMonitor . lock ( ) ;
2025-01-25 20:36:44 +00:00
2025-02-06 11:21:04 +00:00
Debug : : log ( TRACE , " sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {}) " , ( uintptr_t ) this , this - > m_szTitle , m_vRealPosition - > goal ( ) ,
m_vRealSize - > goal ( ) , force ) ;
2025-01-25 20:36:44 +00:00
// TODO: this should be decoupled from setWindowSize IMO
2025-02-16 00:20:42 +00:00
const auto REPORTPOS = realToReportPosition ( ) ;
2025-01-25 20:36:44 +00:00
2025-02-16 00:20:42 +00:00
const auto REPORTSIZE = realToReportSize ( ) ;
2025-01-25 20:36:44 +00:00
2025-02-16 00:20:42 +00:00
if ( ! force & & m_vPendingReportedSize = = REPORTSIZE & & ( m_vReportedPosition = = REPORTPOS | | ! m_bIsX11 ) )
2025-01-25 20:36:44 +00:00
return ;
2025-02-16 00:20:42 +00:00
m_vReportedPosition = REPORTPOS ;
m_vPendingReportedSize = REPORTSIZE ;
updateX11SurfaceScale ( ) ;
2025-01-25 20:36:44 +00:00
if ( m_bIsX11 & & m_pXWaylandSurface )
2025-02-16 00:20:42 +00:00
m_pXWaylandSurface - > configure ( { REPORTPOS , REPORTSIZE } ) ;
2025-01-25 20:36:44 +00:00
else if ( m_pXDGSurface & & m_pXDGSurface - > toplevel )
2025-02-16 00:20:42 +00:00
m_vPendingSizeAcks . emplace_back ( m_pXDGSurface - > toplevel - > setSize ( REPORTSIZE ) , REPORTPOS . floor ( ) ) ;
2025-01-25 20:36:44 +00:00
}
2025-02-02 22:25:29 +03:00
NContentType : : eContentType CWindow : : getContentType ( ) {
2025-02-06 06:16:47 -05:00
if ( ! m_pWLSurface | | ! m_pWLSurface - > resource ( ) | | ! m_pWLSurface - > resource ( ) - > contentType . valid ( ) )
return CONTENT_TYPE_NONE ;
return m_pWLSurface - > resource ( ) - > contentType - > value ;
2025-02-02 22:25:29 +03:00
}
void CWindow : : setContentType ( NContentType : : eContentType contentType ) {
if ( ! m_pWLSurface - > resource ( ) - > contentType . valid ( ) )
m_pWLSurface - > resource ( ) - > contentType = PROTO : : contentType - > getContentType ( m_pWLSurface - > resource ( ) ) ;
// else disallow content type change if proto is used?
Debug : : log ( INFO , " ContentType for window {} " , ( int ) contentType ) ;
m_pWLSurface - > resource ( ) - > contentType - > value = contentType ;
}
2025-02-08 09:05:44 -05:00
void CWindow : : deactivateGroupMembers ( ) {
auto curr = getGroupHead ( ) ;
while ( curr ) {
if ( curr ! = m_pSelf . lock ( ) ) {
2025-04-01 18:51:37 -04:00
// we dont want to deactivate unfocused xwayland windows
// because X is weird, keep the behavior for wayland windows
// also its not really needed for xwayland windows
// ref: #9760 #9294
if ( ! curr - > m_bIsX11 & & curr - > m_pXDGSurface & & curr - > m_pXDGSurface - > toplevel )
2025-02-08 09:05:44 -05:00
curr - > m_pXDGSurface - > toplevel - > setActive ( false ) ;
}
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
if ( curr = = getGroupHead ( ) )
break ;
}
}
2025-02-18 15:10:40 +00:00
bool CWindow : : isNotResponding ( ) {
2025-02-21 21:26:53 +01:00
return g_pANRManager - > isNotResponding ( m_pSelf . lock ( ) ) ;
2025-02-18 15:10:40 +00:00
}