2022-03-21 15:17:04 +01:00
# include "Events.hpp"
# include "../Compositor.hpp"
# include "../helpers/WLClasses.hpp"
2025-04-29 18:20:06 +01:00
# include "../helpers/AsyncDialogBox.hpp"
2022-06-09 12:46:55 +02:00
# include "../managers/input/InputManager.hpp"
2024-04-23 01:28:20 +01:00
# include "../managers/TokenManager.hpp"
2024-05-10 18:27:57 +01:00
# include "../managers/SeatManager.hpp"
2022-03-21 15:17:04 +01:00
# include "../render/Renderer.hpp"
2024-03-03 18:39:20 +00:00
# include "../config/ConfigValue.hpp"
2025-04-15 23:00:40 +00:00
# include "../config/ConfigManager.hpp"
2024-05-09 21:47:21 +01:00
# include "../protocols/LayerShell.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"
2024-07-27 10:02:02 -05:00
# include "../protocols/ToplevelExport.hpp"
2025-02-02 22:16:00 +00:00
# include "../protocols/types/ContentType.hpp"
2024-05-25 22:43:51 +02:00
# include "../xwayland/XSurface.hpp"
2025-01-07 17:55:14 +00:00
# include "managers/AnimationManager.hpp"
2024-10-12 03:29:51 +03:00
# include "managers/PointerManager.hpp"
2025-01-17 15:21:35 +00:00
# include "../desktop/LayerSurface.hpp"
# include "../managers/LayoutManager.hpp"
# include "../managers/EventManager.hpp"
# include "../managers/AnimationManager.hpp"
2022-03-21 15:17:04 +01:00
2024-06-11 17:17:45 +02:00
# include <hyprutils/string/String.hpp>
using namespace Hyprutils : : String ;
2025-01-07 17:55:14 +00:00
using namespace Hyprutils : : Animation ;
2024-06-11 17:17:45 +02:00
2022-03-21 15:17:04 +01:00
// ------------------------------------------------------------ //
// __ _______ _ _ _____ ______ _______ //
// \ \ / /_ _| \ | | __ \ / __ \ \ / / ____| //
// \ \ /\ / / | | | \| | | | | | | \ \ /\ / / (___ //
// \ \/ \/ / | | | . ` | | | | | | |\ \/ \/ / \___ \ //
// \ /\ / _| |_| |\ | |__| | |__| | \ /\ / ____) | //
// \/ \/ |_____|_| \_|_____/ \____/ \/ \/ |_____/ //
// //
// ------------------------------------------------------------ //
2025-01-07 17:55:14 +00:00
static void setVector2DAnimToMove ( WP < CBaseAnimatedVariable > pav ) {
const auto PAV = pav . lock ( ) ;
if ( ! PAV )
return ;
2022-07-28 13:28:43 +02:00
2025-01-07 17:55:14 +00:00
CAnimatedVariable < Vector2D > * animvar = dynamic_cast < CAnimatedVariable < Vector2D > * > ( PAV . get ( ) ) ;
animvar - > setConfig ( g_pConfigManager - > getAnimationPropertyConfig ( " windowsMove " ) ) ;
2024-05-06 07:32:01 -07:00
2025-01-07 17:55:14 +00:00
const auto PHLWINDOW = animvar - > m_Context . pWindow . lock ( ) ;
2025-01-25 02:35:41 +00:00
if ( PHLWINDOW )
2025-04-28 22:25:22 +02:00
PHLWINDOW - > m_animatingIn = false ;
2022-07-28 13:28:43 +02:00
}
2022-03-28 22:31:39 +02:00
void Events : : listener_mapWindow ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-12-16 17:17:31 +00:00
2024-04-23 01:28:20 +01:00
static auto PINACTIVEALPHA = CConfigValue < Hyprlang : : FLOAT > ( " decoration:inactive_opacity " ) ;
static auto PACTIVEALPHA = CConfigValue < Hyprlang : : FLOAT > ( " decoration:active_opacity " ) ;
static auto PDIMSTRENGTH = CConfigValue < Hyprlang : : FLOAT > ( " decoration:dim_strength " ) ;
static auto PNEWTAKESOVERFS = CConfigValue < Hyprlang : : INT > ( " misc:new_window_takes_over_fullscreen " ) ;
static auto PINITIALWSTRACKING = CConfigValue < Hyprlang : : INT > ( " misc:initial_workspace_tracking " ) ;
2022-12-16 17:17:31 +00:00
2025-04-22 15:23:29 +02:00
auto PMONITOR = g_pCompositor - > m_lastMonitor . lock ( ) ;
if ( ! g_pCompositor - > m_lastMonitor ) {
2024-03-26 02:26:09 +00:00
g_pCompositor - > setActiveMonitor ( g_pCompositor - > getMonitorFromVector ( { } ) ) ;
2025-04-22 15:23:29 +02:00
PMONITOR = g_pCompositor - > m_lastMonitor . lock ( ) ;
2024-03-26 02:26:09 +00:00
}
2025-04-30 23:45:20 +02:00
auto PWORKSPACE = PMONITOR - > m_activeSpecialWorkspace ? PMONITOR - > m_activeSpecialWorkspace : PMONITOR - > m_activeWorkspace ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = PMONITOR ;
PWINDOW - > m_workspace = PWORKSPACE ;
PWINDOW - > m_isMapped = true ;
PWINDOW - > m_readyToDelete = false ;
PWINDOW - > m_fadingOut = false ;
PWINDOW - > m_title = PWINDOW - > fetchTitle ( ) ;
PWINDOW - > m_firstMap = true ;
PWINDOW - > m_initialTitle = PWINDOW - > m_title ;
PWINDOW - > m_initialClass = PWINDOW - > fetchClass ( ) ;
2022-03-21 15:17:04 +01:00
2024-04-23 01:28:20 +01:00
// check for token
std : : string requestedWorkspace = " " ;
bool workspaceSilent = false ;
if ( * PINITIALWSTRACKING ) {
const auto WINDOWENV = PWINDOW - > getEnv ( ) ;
if ( WINDOWENV . contains ( " HL_INITIAL_WORKSPACE_TOKEN " ) ) {
const auto SZTOKEN = WINDOWENV . at ( " HL_INITIAL_WORKSPACE_TOKEN " ) ;
Debug : : log ( LOG , " New window contains HL_INITIAL_WORKSPACE_TOKEN: {} " , SZTOKEN ) ;
const auto TOKEN = g_pTokenManager - > getToken ( SZTOKEN ) ;
if ( TOKEN ) {
// find workspace and use it
2025-04-16 01:37:48 +01:00
SInitialWorkspaceToken WS = std : : any_cast < SInitialWorkspaceToken > ( TOKEN - > m_data ) ;
2024-04-23 01:28:20 +01:00
2024-04-24 16:16:46 +01:00
Debug : : log ( LOG , " HL_INITIAL_WORKSPACE_TOKEN {} -> {} " , SZTOKEN , WS . workspace ) ;
2024-04-23 01:28:20 +01:00
2025-04-28 22:25:22 +02:00
if ( g_pCompositor - > getWorkspaceByString ( WS . workspace ) ! = PWINDOW - > m_workspace ) {
2024-04-24 16:16:46 +01:00
requestedWorkspace = WS . workspace ;
2024-04-23 11:37:12 +01:00
workspaceSilent = true ;
}
2024-04-24 16:16:46 +01:00
if ( * PINITIALWSTRACKING = = 1 ) // one-shot token
g_pTokenManager - > removeToken ( TOKEN ) ;
else if ( * PINITIALWSTRACKING = = 2 ) { // persistent
2024-04-27 12:43:12 +01:00
if ( WS . primaryOwner . expired ( ) ) {
2024-04-24 16:16:46 +01:00
WS . primaryOwner = PWINDOW ;
2025-04-16 01:37:48 +01:00
TOKEN - > m_data = WS ;
2024-04-24 16:16:46 +01:00
}
2025-04-28 22:25:22 +02:00
PWINDOW - > m_initialWorkspaceToken = SZTOKEN ;
2024-04-24 16:16:46 +01:00
}
2024-04-23 01:28:20 +01:00
}
}
}
2025-05-01 23:57:11 +02:00
if ( g_pInputManager - > m_lastFocusOnLS ) // waybar fix
2023-01-11 18:38:54 +01:00
g_pInputManager - > releaseAllMouseButtons ( ) ;
2023-03-30 00:44:25 +02:00
// checks if the window wants borders and sets the appropriate flag
2022-03-22 21:28:57 +01:00
g_pXWaylandManager - > checkBorders ( PWINDOW ) ;
2022-11-04 15:56:31 +00:00
// registers the animated vars and stuff
PWINDOW - > onMap ( ) ;
2025-04-28 22:25:22 +02:00
const auto PWINDOWSURFACE = PWINDOW - > m_wlSurface - > resource ( ) ;
2022-03-21 17:00:17 +01:00
if ( ! PWINDOWSURFACE ) {
2022-06-30 15:44:26 +02:00
g_pCompositor - > removeWindowFromVectorSafe ( PWINDOW ) ;
2022-03-21 17:00:17 +01:00
return ;
}
2022-05-26 19:05:32 +02:00
if ( g_pXWaylandManager - > shouldBeFloated ( PWINDOW ) ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isFloating = true ;
PWINDOW - > m_requestsFloat = true ;
2022-05-26 19:05:32 +02:00
}
2025-04-28 22:25:22 +02:00
PWINDOW - > m_X11ShouldntFocus = PWINDOW - > m_X11ShouldntFocus | | ( PWINDOW - > m_isX11 & & PWINDOW - > isX11OverrideRedirect ( ) & & ! PWINDOW - > m_xwaylandSurface - > wantsFocus ( ) ) ;
2022-08-20 18:00:50 +02:00
2022-03-24 18:22:01 +01:00
// window rules
2025-04-28 22:25:22 +02:00
PWINDOW - > m_matchedRules = g_pConfigManager - > getMatchingRules ( PWINDOW , false ) ;
2024-07-31 17:55:52 +00:00
std : : optional < eFullscreenMode > requestedInternalFSMode , requestedClientFSMode ;
2024-12-07 18:51:18 +01:00
std : : optional < SFullscreenState > requestedFSState ;
2025-05-07 15:21:44 +02:00
if ( PWINDOW - > m_wantsInitialFullscreen | | ( PWINDOW - > m_isX11 & & PWINDOW - > m_xwaylandSurface - > m_fullscreen ) )
2024-07-31 17:55:52 +00:00
requestedClientFSMode = FSMODE_FULLSCREEN ;
2025-04-28 22:25:22 +02:00
MONITORID requestedFSMonitor = PWINDOW - > m_wantsInitialFullscreenMonitor ;
2022-03-24 18:22:01 +01:00
2025-04-28 22:25:22 +02:00
for ( auto const & r : PWINDOW - > m_matchedRules ) {
switch ( r - > m_ruleType ) {
2024-12-16 19:05:24 +01:00
case CWindowRule : : RULE_MONITOR : {
try {
2025-04-28 22:25:22 +02:00
const auto MONITORSTR = trim ( r - > m_rule . substr ( r - > m_rule . find ( ' ' ) ) ) ;
2022-03-24 18:22:01 +01:00
2024-12-16 19:05:24 +01:00
if ( MONITORSTR = = " unset " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = PMONITOR ;
2023-03-18 01:33:48 +00:00
} else {
2024-12-16 19:05:24 +01:00
if ( isNumber ( MONITORSTR ) ) {
const MONITORID MONITOR = std : : stoi ( MONITORSTR ) ;
if ( const auto PM = g_pCompositor - > getMonitorFromID ( MONITOR ) ; PM )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = PM ;
2024-12-16 19:05:24 +01:00
else
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = g_pCompositor - > m_monitors . at ( 0 ) ;
2024-12-16 19:05:24 +01:00
} else {
const auto PMONITOR = g_pCompositor - > getMonitorFromName ( MONITORSTR ) ;
if ( PMONITOR )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = PMONITOR ;
2024-12-16 19:05:24 +01:00
else {
Debug : : log ( ERR , " No monitor in monitor {} rule " , MONITORSTR ) ;
continue ;
}
2023-03-18 01:33:48 +00:00
}
}
2022-03-24 18:22:01 +01:00
2025-04-28 22:25:22 +02:00
const auto PMONITORFROMID = PWINDOW - > m_monitor . lock ( ) ;
2023-08-25 18:05:08 +02:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_monitor ! = PMONITOR ) {
2025-05-02 17:07:20 +02:00
g_pKeybindManager - > m_dispatchers [ " focusmonitor " ] ( std : : to_string ( PWINDOW - > monitorID ( ) ) ) ;
2024-12-16 19:05:24 +01:00
PMONITOR = PMONITORFROMID ;
}
2025-04-30 23:45:20 +02:00
PWINDOW - > m_workspace = PMONITOR - > m_activeSpecialWorkspace ? PMONITOR - > m_activeSpecialWorkspace : PMONITOR - > m_activeWorkspace ;
2025-04-28 22:25:22 +02:00
PWORKSPACE = PWINDOW - > m_workspace ;
2022-04-21 17:17:47 +02:00
2024-12-16 19:05:24 +01:00
Debug : : log ( LOG , " Rule monitor, applying to {:mw} " , PWINDOW ) ;
2025-01-09 17:38:38 -05:00
requestedFSMonitor = MONITOR_INVALID ;
2025-04-28 22:25:22 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule monitor failed, rule: {} -> {} | err: {} " , r - > m_rule , r - > m_value , e . what ( ) ) ; }
2024-12-16 19:05:24 +01:00
break ;
2024-02-14 22:19:49 +00:00
}
2024-12-16 19:05:24 +01:00
case CWindowRule : : RULE_WORKSPACE : {
// check if it isnt unset
2025-04-28 22:25:22 +02:00
const auto WORKSPACERQ = r - > m_rule . substr ( r - > m_rule . find_first_of ( ' ' ) + 1 ) ;
2023-09-21 23:42:00 +00:00
2025-01-04 17:21:02 +01:00
if ( WORKSPACERQ = = " unset " )
2024-12-16 19:05:24 +01:00
requestedWorkspace = " " ;
2025-01-04 17:21:02 +01:00
else
2024-12-16 19:05:24 +01:00
requestedWorkspace = WORKSPACERQ ;
2023-09-21 23:42:00 +00:00
2024-12-16 19:05:24 +01:00
const auto JUSTWORKSPACE = WORKSPACERQ . contains ( ' ' ) ? WORKSPACERQ . substr ( 0 , WORKSPACERQ . find_first_of ( ' ' ) ) : WORKSPACERQ ;
2023-09-21 23:42:00 +00:00
2025-04-25 02:37:12 +02:00
if ( JUSTWORKSPACE = = PWORKSPACE - > m_name | | JUSTWORKSPACE = = " name: " + PWORKSPACE - > m_name )
2024-12-16 19:05:24 +01:00
requestedWorkspace = " " ;
2025-04-28 22:25:22 +02:00
Debug : : log ( LOG , " Rule workspace matched by {}, {} applied. " , PWINDOW , r - > m_value ) ;
2025-01-09 17:38:38 -05:00
requestedFSMonitor = MONITOR_INVALID ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_FLOAT : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isFloating = true ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_TILE : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isFloating = false ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_PSEUDO : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isPseudotiled = true ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_NOINITIALFOCUS : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_noInitialFocus = true ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_FULLSCREENSTATE : {
2025-04-28 22:25:22 +02:00
const auto ARGS = CVarList ( r - > m_rule . substr ( r - > m_rule . find_first_of ( ' ' ) + 1 ) , 2 , ' ' ) ;
2024-12-16 19:05:24 +01:00
int internalMode , clientMode ;
try {
internalMode = std : : stoi ( ARGS [ 0 ] ) ;
} catch ( std : : exception & e ) { internalMode = 0 ; }
try {
clientMode = std : : stoi ( ARGS [ 1 ] ) ;
} catch ( std : : exception & e ) { clientMode = 0 ; }
requestedFSState = SFullscreenState { . internal = ( eFullscreenMode ) internalMode , . client = ( eFullscreenMode ) clientMode } ;
break ;
}
case CWindowRule : : RULE_SUPPRESSEVENT : {
2025-04-28 22:25:22 +02:00
CVarList vars ( r - > m_rule , 0 , ' s ' , true ) ;
2024-12-16 19:05:24 +01:00
for ( size_t i = 1 ; i < vars . size ( ) ; + + i ) {
if ( vars [ i ] = = " fullscreen " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_suppressedEvents | = SUPPRESS_FULLSCREEN ;
2024-12-16 19:05:24 +01:00
else if ( vars [ i ] = = " maximize " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_suppressedEvents | = SUPPRESS_MAXIMIZE ;
2024-12-16 19:05:24 +01:00
else if ( vars [ i ] = = " activate " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_suppressedEvents | = SUPPRESS_ACTIVATE ;
2024-12-16 19:05:24 +01:00
else if ( vars [ i ] = = " activatefocus " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_suppressedEvents | = SUPPRESS_ACTIVATE_FOCUSONLY ;
2025-01-09 17:38:38 -05:00
else if ( vars [ i ] = = " fullscreenoutput " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_suppressedEvents | = SUPPRESS_FULLSCREEN_OUTPUT ;
2024-12-16 19:05:24 +01:00
else
Debug : : log ( ERR , " Error while parsing suppressevent windowrule: unknown event type {} " , vars [ i ] ) ;
}
break ;
}
case CWindowRule : : RULE_PIN : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_pinned = true ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_FULLSCREEN : {
requestedInternalFSMode = FSMODE_FULLSCREEN ;
break ;
}
case CWindowRule : : RULE_MAXIMIZE : {
requestedInternalFSMode = FSMODE_MAXIMIZED ;
break ;
}
case CWindowRule : : RULE_STAYFOCUSED : {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_stayFocused = true ;
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_GROUP : {
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_groupRules & GROUP_OVERRIDE )
2023-09-21 23:42:00 +00:00
continue ;
2024-12-16 19:05:24 +01:00
// `group` is a shorthand of `group set`
2025-04-28 22:25:22 +02:00
if ( trim ( r - > m_rule ) = = " group " ) {
PWINDOW - > m_groupRules | = GROUP_SET ;
2024-12-16 19:05:24 +01:00
continue ;
}
2025-04-28 22:25:22 +02:00
CVarList vars ( r - > m_rule , 0 , ' s ' ) ;
2024-12-16 19:05:24 +01:00
std : : string vPrev = " " ;
for ( auto const & v : vars ) {
if ( v = = " group " )
continue ;
if ( v = = " set " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_SET ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " new " ) {
// shorthand for `group barred set`
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = ( GROUP_SET | GROUP_BARRED ) ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " lock " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_LOCK ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " invade " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_INVADE ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " barred " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_BARRED ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " deny " ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupData . deny = true ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " override " ) {
// Clear existing rules
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules = GROUP_OVERRIDE ;
2024-12-16 19:05:24 +01:00
} else if ( v = = " unset " ) {
// Clear existing rules and stop processing
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules = GROUP_OVERRIDE ;
2024-12-16 19:05:24 +01:00
break ;
} else if ( v = = " always " ) {
if ( vPrev = = " set " | | vPrev = = " group " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_SET_ALWAYS ;
2024-12-16 19:05:24 +01:00
else if ( vPrev = = " lock " )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_groupRules | = GROUP_LOCK_ALWAYS ;
2024-12-16 19:05:24 +01:00
else
Debug : : log ( ERR , " windowrule `group` does not support `{} always` " , vPrev ) ;
}
vPrev = v ;
2023-09-21 23:42:00 +00:00
}
2024-12-16 19:05:24 +01:00
break ;
2023-09-21 23:42:00 +00:00
}
2025-02-02 22:25:29 +03:00
case CWindowRule : : RULE_CONTENT : {
2025-04-28 22:25:22 +02:00
const CVarList VARS ( r - > m_rule , 0 , ' ' ) ;
2025-02-02 22:25:29 +03:00
try {
PWINDOW - > setContentType ( NContentType : : fromString ( VARS [ 1 ] ) ) ;
2025-04-28 22:25:22 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" {} \" failed with: {} " , r - > m_rule , e . what ( ) ) ; }
2025-02-02 22:25:29 +03:00
break ;
}
2025-04-29 18:14:02 +01:00
case CWindowRule : : RULE_NOCLOSEFOR : {
const CVarList VARS ( r - > m_rule , 0 , ' ' ) ;
try {
PWINDOW - > m_closeableSince = Time : : steadyNow ( ) + std : : chrono : : milliseconds ( std : : stoull ( VARS [ 1 ] ) ) ;
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" {} \" failed with: {} " , r - > m_rule , e . what ( ) ) ; }
}
2024-12-16 19:05:24 +01:00
default : break ;
2022-03-24 18:22:01 +01:00
}
2024-12-16 19:05:24 +01:00
2022-11-15 11:21:26 +01:00
PWINDOW - > applyDynamicRule ( r ) ;
2022-03-24 18:22:01 +01:00
}
2025-04-29 18:20:06 +01:00
// make it uncloseable if it's a Hyprland dialog
// TODO: make some closeable?
if ( CAsyncDialogBox : : isAsyncDialogBox ( PWINDOW - > getPID ( ) ) )
PWINDOW - > m_closeableSince = Time : : steadyNow ( ) + std : : chrono : : years ( 10 /* Should be enough, no? */ ) ;
2022-09-10 13:11:02 +02:00
// disallow tiled pinned
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_pinned & & ! PWINDOW - > m_isFloating )
PWINDOW - > m_pinned = false ;
2022-09-10 13:11:02 +02:00
2025-05-04 13:22:41 -04:00
CVarList WORKSPACEARGS = CVarList ( requestedWorkspace , 0 , ' ' ) ;
2022-08-25 16:47:28 +02:00
2023-09-02 18:41:02 +00:00
if ( ! WORKSPACEARGS [ 0 ] . empty ( ) ) {
2025-05-04 13:22:41 -04:00
WORKSPACEID requestedWorkspaceID ;
std : : string requestedWorkspaceName ;
if ( WORKSPACEARGS . contains ( " silent " ) )
2023-09-12 16:50:07 +01:00
workspaceSilent = true ;
2022-06-01 21:04:06 +02:00
2025-05-04 13:22:41 -04:00
if ( WORKSPACEARGS . contains ( " empty " ) & & PWORKSPACE - > getWindows ( ) < = 1 ) {
requestedWorkspaceID = PWORKSPACE - > m_id ;
requestedWorkspaceName = PWORKSPACE - > m_name ;
} else {
auto result = getWorkspaceIDNameFromString ( WORKSPACEARGS . join ( " " , 0 , workspaceSilent ? WORKSPACEARGS . size ( ) - 1 : 0 ) ) ;
requestedWorkspaceID = result . id ;
requestedWorkspaceName = result . name ;
}
2022-11-26 15:41:08 +00:00
2025-05-04 13:22:41 -04:00
if ( requestedWorkspaceID ! = WORKSPACE_INVALID ) {
auto pWorkspace = g_pCompositor - > getWorkspaceByID ( requestedWorkspaceID ) ;
2022-06-01 21:04:06 +02:00
2023-09-02 18:41:02 +00:00
if ( ! pWorkspace )
2025-05-04 13:22:41 -04:00
pWorkspace = g_pCompositor - > createNewWorkspace ( requestedWorkspaceID , PWINDOW - > monitorID ( ) , requestedWorkspaceName , false ) ;
2022-10-24 18:36:31 +01:00
2024-02-25 15:09:41 +01:00
PWORKSPACE = pWorkspace ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_workspace = pWorkspace ;
PWINDOW - > m_monitor = pWorkspace - > m_monitor ;
2022-10-24 18:36:31 +01:00
2025-04-30 23:45:20 +02:00
if ( PWINDOW - > m_monitor . lock ( ) - > m_activeSpecialWorkspace & & ! pWorkspace - > m_isSpecialWorkspace )
2023-09-03 15:23:13 +00:00
workspaceSilent = true ;
2023-09-02 18:41:02 +00:00
if ( ! workspaceSilent ) {
2025-04-25 02:37:12 +02:00
if ( pWorkspace - > m_isSpecialWorkspace )
pWorkspace - > m_monitor - > setSpecialWorkspace ( pWorkspace ) ;
2025-05-04 13:22:41 -04:00
else if ( PMONITOR - > activeWorkspaceID ( ) ! = requestedWorkspaceID & & ! PWINDOW - > m_noInitialFocus )
2025-05-02 17:07:20 +02:00
g_pKeybindManager - > m_dispatchers [ " workspace " ] ( requestedWorkspaceName ) ;
2022-11-13 20:33:13 +01:00
2025-04-22 15:23:29 +02:00
PMONITOR = g_pCompositor - > m_lastMonitor . lock ( ) ;
2022-10-24 18:36:31 +01:00
}
2025-01-09 17:38:38 -05:00
requestedFSMonitor = MONITOR_INVALID ;
2023-09-12 16:50:07 +01:00
} else
workspaceSilent = false ;
2022-10-24 18:36:31 +01:00
}
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_suppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT )
2025-01-09 17:38:38 -05:00
requestedFSMonitor = MONITOR_INVALID ;
else if ( requestedFSMonitor ! = MONITOR_INVALID ) {
if ( const auto PM = g_pCompositor - > getMonitorFromID ( requestedFSMonitor ) ; PM )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_monitor = PM ;
2025-01-09 17:38:38 -05:00
2025-04-28 22:25:22 +02:00
const auto PMONITORFROMID = PWINDOW - > m_monitor . lock ( ) ;
2025-01-09 17:38:38 -05:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_monitor ! = PMONITOR ) {
2025-05-02 17:07:20 +02:00
g_pKeybindManager - > m_dispatchers [ " focusmonitor " ] ( std : : to_string ( PWINDOW - > monitorID ( ) ) ) ;
2025-01-09 17:38:38 -05:00
PMONITOR = PMONITORFROMID ;
}
2025-04-30 23:45:20 +02:00
PWINDOW - > m_workspace = PMONITOR - > m_activeSpecialWorkspace ? PMONITOR - > m_activeSpecialWorkspace : PMONITOR - > m_activeWorkspace ;
2025-04-28 22:25:22 +02:00
PWORKSPACE = PWINDOW - > m_workspace ;
2025-01-09 17:38:38 -05:00
Debug : : log ( LOG , " Requested monitor, applying to {:mw} " , PWINDOW ) ;
}
2025-04-25 02:37:12 +02:00
if ( PWORKSPACE - > m_defaultFloating )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isFloating = true ;
2025-01-04 17:21:02 +01:00
2025-04-25 02:37:12 +02:00
if ( PWORKSPACE - > m_defaultPseudo ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isPseudotiled = true ;
CBox desiredGeometry = g_pXWaylandManager - > getGeometryForWindow ( PWINDOW ) ;
PWINDOW - > m_pseudoSize = Vector2D ( desiredGeometry . width , desiredGeometry . height ) ;
2025-01-04 17:21:02 +01:00
}
2024-07-11 14:10:42 +00:00
PWINDOW - > updateWindowData ( ) ;
2024-03-02 22:15:07 +00:00
2024-10-27 00:44:55 +00:00
// Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped.
2025-04-28 22:25:22 +02:00
const auto SWALLOWER = PWINDOW - > getSwallower ( ) ;
PWINDOW - > m_swallowed = SWALLOWER ;
if ( PWINDOW - > m_swallowed )
PWINDOW - > m_swallowed - > m_currentlySwallowed = true ;
2024-10-27 00:44:55 +00:00
2025-05-08 22:10:31 +02:00
// emit the IPC event before the layout might focus the window to avoid a focus event first
g_pEventManager - > postEvent (
SHyprIPCEvent { " openwindow " , std : : format ( " {:x},{},{},{} " , PWINDOW , requestedWorkspace ! = " " ? requestedWorkspace : PWORKSPACE - > m_name , PWINDOW - > m_class , PWINDOW - > m_title ) } ) ;
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_isFloating ) {
2024-10-02 11:22:19 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreated ( PWINDOW ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_createdOverFullscreen = true ;
2022-03-24 18:22:01 +01:00
// size and move rules
2025-04-28 22:25:22 +02:00
for ( auto const & r : PWINDOW - > m_matchedRules ) {
switch ( r - > m_ruleType ) {
2024-12-16 19:05:24 +01:00
case CWindowRule : : RULE_SIZE : {
try {
auto stringToFloatClamp = [ ] ( const std : : string & VALUE , const float CURR , const float REL ) {
if ( VALUE . starts_with ( ' < ' ) )
return std : : min ( CURR , stringToPercentage ( VALUE . substr ( 1 , VALUE . length ( ) - 1 ) , REL ) ) ;
else if ( VALUE . starts_with ( ' > ' ) )
return std : : max ( CURR , stringToPercentage ( VALUE . substr ( 1 , VALUE . length ( ) - 1 ) , REL ) ) ;
2024-10-17 20:03:17 +00:00
2024-12-16 19:05:24 +01:00
return stringToPercentage ( VALUE , REL ) ;
} ;
2024-10-17 20:03:17 +00:00
2025-04-28 22:25:22 +02:00
const auto VALUE = r - > m_rule . substr ( r - > m_rule . find ( ' ' ) + 1 ) ;
2024-12-16 19:05:24 +01:00
const auto SIZEXSTR = VALUE . substr ( 0 , VALUE . find ( ' ' ) ) ;
const auto SIZEYSTR = VALUE . substr ( VALUE . find ( ' ' ) + 1 ) ;
2024-10-17 20:03:17 +00:00
2024-12-16 19:05:24 +01:00
const auto MAXSIZE = PWINDOW - > requestedMaxSize ( ) ;
2024-10-17 20:03:17 +00:00
2025-04-30 23:45:20 +02:00
const float SIZEX = SIZEXSTR = = " max " ? std : : clamp ( MAXSIZE . x , MIN_WINDOW_SIZE , PMONITOR - > m_size . x ) :
stringToFloatClamp ( SIZEXSTR , PWINDOW - > m_realSize - > goal ( ) . x , PMONITOR - > m_size . x ) ;
2024-10-17 20:03:17 +00:00
2025-04-30 23:45:20 +02:00
const float SIZEY = SIZEYSTR = = " max " ? std : : clamp ( MAXSIZE . y , MIN_WINDOW_SIZE , PMONITOR - > m_size . y ) :
stringToFloatClamp ( SIZEYSTR , PWINDOW - > m_realSize - > goal ( ) . y , PMONITOR - > m_size . y ) ;
2022-03-24 18:22:01 +01:00
2024-12-16 19:05:24 +01:00
Debug : : log ( LOG , " Rule size, applying to {} " , PWINDOW ) ;
2022-03-24 18:22:01 +01:00
2024-12-16 19:05:24 +01:00
PWINDOW - > clampWindowSize ( Vector2D { SIZEXSTR . starts_with ( " < " ) ? 0 : SIZEX , SIZEYSTR . starts_with ( " < " ) ? 0 : SIZEY } , Vector2D { SIZEX , SIZEY } ) ;
2022-07-30 12:42:27 +02:00
2024-12-16 19:05:24 +01:00
PWINDOW - > setHidden ( false ) ;
2025-04-28 22:25:22 +02:00
} catch ( . . . ) { Debug : : log ( LOG , " Rule size failed, rule: {} -> {} " , r - > m_rule , r - > m_value ) ; }
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_MOVE : {
try {
2025-04-28 22:25:22 +02:00
auto value = r - > m_rule . substr ( r - > m_rule . find ( ' ' ) + 1 ) ;
2022-11-10 16:59:08 +00:00
2024-12-16 19:05:24 +01:00
const bool ONSCREEN = value . starts_with ( " onscreen " ) ;
2023-09-12 04:56:20 -04:00
2024-12-16 19:05:24 +01:00
if ( ONSCREEN )
value = value . substr ( value . find_first_of ( ' ' ) + 1 ) ;
2023-09-12 04:56:20 -04:00
2024-12-16 19:05:24 +01:00
const bool CURSOR = value . starts_with ( " cursor " ) ;
2022-11-10 16:59:08 +00:00
2024-12-16 19:05:24 +01:00
if ( CURSOR )
value = value . substr ( value . find_first_of ( ' ' ) + 1 ) ;
2022-11-10 16:59:08 +00:00
2024-12-16 19:05:24 +01:00
const auto POSXSTR = value . substr ( 0 , value . find ( ' ' ) ) ;
const auto POSYSTR = value . substr ( value . find ( ' ' ) + 1 ) ;
2022-04-22 14:31:14 +02:00
2024-12-16 19:05:24 +01:00
int posX = 0 ;
int posY = 0 ;
2022-10-26 12:34:26 +01:00
2024-12-16 19:05:24 +01:00
if ( POSXSTR . starts_with ( " 100%- " ) ) {
const bool subtractWindow = POSXSTR . starts_with ( " 100%-w- " ) ;
const auto POSXRAW = ( subtractWindow ) ? POSXSTR . substr ( 7 ) : POSXSTR . substr ( 5 ) ;
2025-04-30 23:45:20 +02:00
posX =
PMONITOR - > m_size . x - ( ! POSXRAW . contains ( ' % ' ) ? std : : stoi ( POSXRAW ) : std : : stof ( POSXRAW . substr ( 0 , POSXRAW . length ( ) - 1 ) ) * 0.01 * PMONITOR - > m_size . x ) ;
2022-11-10 16:59:08 +00:00
2024-12-16 19:05:24 +01:00
if ( subtractWindow )
2025-04-28 22:25:22 +02:00
posX - = PWINDOW - > m_realSize - > goal ( ) . x ;
2024-04-27 18:34:19 +02:00
2024-12-16 19:05:24 +01:00
if ( CURSOR )
Debug : : log ( ERR , " Cursor is not compatible with 100%-, ignoring cursor! " ) ;
} else if ( ! CURSOR ) {
2025-04-30 23:45:20 +02:00
posX = ! POSXSTR . contains ( ' % ' ) ? std : : stoi ( POSXSTR ) : std : : stof ( POSXSTR . substr ( 0 , POSXSTR . length ( ) - 1 ) ) * 0.01 * PMONITOR - > m_size . x ;
2022-11-10 16:59:08 +00:00
} else {
2024-12-16 19:05:24 +01:00
// cursor
if ( POSXSTR = = " cursor " ) {
2025-04-30 23:45:20 +02:00
posX = g_pInputManager - > getMouseCoordsInternal ( ) . x - PMONITOR - > m_position . x ;
2024-12-16 19:05:24 +01:00
} else {
2025-04-30 23:45:20 +02:00
posX = g_pInputManager - > getMouseCoordsInternal ( ) . x - PMONITOR - > m_position . x +
2025-04-28 22:25:22 +02:00
( ! POSXSTR . contains ( ' % ' ) ? std : : stoi ( POSXSTR ) : std : : stof ( POSXSTR . substr ( 0 , POSXSTR . length ( ) - 1 ) ) * 0.01 * PWINDOW - > m_realSize - > goal ( ) . x ) ;
2024-12-16 19:05:24 +01:00
}
2022-11-10 16:59:08 +00:00
}
2022-10-26 12:34:26 +01:00
2024-12-16 19:05:24 +01:00
if ( POSYSTR . starts_with ( " 100%- " ) ) {
const bool subtractWindow = POSYSTR . starts_with ( " 100%-w- " ) ;
const auto POSYRAW = ( subtractWindow ) ? POSYSTR . substr ( 7 ) : POSYSTR . substr ( 5 ) ;
2025-04-30 23:45:20 +02:00
posY =
PMONITOR - > m_size . y - ( ! POSYRAW . contains ( ' % ' ) ? std : : stoi ( POSYRAW ) : std : : stof ( POSYRAW . substr ( 0 , POSYRAW . length ( ) - 1 ) ) * 0.01 * PMONITOR - > m_size . y ) ;
2022-11-10 16:59:08 +00:00
2024-12-16 19:05:24 +01:00
if ( subtractWindow )
2025-04-28 22:25:22 +02:00
posY - = PWINDOW - > m_realSize - > goal ( ) . y ;
2024-04-27 18:34:19 +02:00
2024-12-16 19:05:24 +01:00
if ( CURSOR )
Debug : : log ( ERR , " Cursor is not compatible with 100%-, ignoring cursor! " ) ;
} else if ( ! CURSOR ) {
2025-04-30 23:45:20 +02:00
posY = ! POSYSTR . contains ( ' % ' ) ? std : : stoi ( POSYSTR ) : std : : stof ( POSYSTR . substr ( 0 , POSYSTR . length ( ) - 1 ) ) * 0.01 * PMONITOR - > m_size . y ;
2022-11-10 16:59:08 +00:00
} else {
2024-12-16 19:05:24 +01:00
// cursor
if ( POSYSTR = = " cursor " ) {
2025-04-30 23:45:20 +02:00
posY = g_pInputManager - > getMouseCoordsInternal ( ) . y - PMONITOR - > m_position . y ;
2024-12-16 19:05:24 +01:00
} else {
2025-04-30 23:45:20 +02:00
posY = g_pInputManager - > getMouseCoordsInternal ( ) . y - PMONITOR - > m_position . y +
2025-04-28 22:25:22 +02:00
( ! POSYSTR . contains ( ' % ' ) ? std : : stoi ( POSYSTR ) : std : : stof ( POSYSTR . substr ( 0 , POSYSTR . length ( ) - 1 ) ) * 0.01 * PWINDOW - > m_realSize - > goal ( ) . y ) ;
2024-12-16 19:05:24 +01:00
}
2022-11-10 16:59:08 +00:00
}
2022-03-24 18:22:01 +01:00
2024-12-16 19:05:24 +01:00
if ( ONSCREEN ) {
int borderSize = PWINDOW - > getRealBorderSize ( ) ;
2023-09-12 04:56:20 -04:00
2025-04-30 23:45:20 +02:00
posX = std : : clamp ( posX , ( int ) ( PMONITOR - > m_reservedTopLeft . x + borderSize ) ,
( int ) ( PMONITOR - > m_size . x - PMONITOR - > m_reservedBottomRight . x - PWINDOW - > m_realSize - > goal ( ) . x - borderSize ) ) ;
2023-09-12 04:56:20 -04:00
2025-04-30 23:45:20 +02:00
posY = std : : clamp ( posY , ( int ) ( PMONITOR - > m_reservedTopLeft . y + borderSize ) ,
( int ) ( PMONITOR - > m_size . y - PMONITOR - > m_reservedBottomRight . y - PWINDOW - > m_realSize - > goal ( ) . y - borderSize ) ) ;
2024-12-16 19:05:24 +01:00
}
2023-09-12 04:56:20 -04:00
2024-12-16 19:05:24 +01:00
Debug : : log ( LOG , " Rule move, applying to {} " , PWINDOW ) ;
2022-03-24 18:22:01 +01:00
2025-04-30 23:45:20 +02:00
* PWINDOW - > m_realPosition = Vector2D ( posX , posY ) + PMONITOR - > m_position ;
2024-12-16 19:05:24 +01:00
PWINDOW - > setHidden ( false ) ;
2025-04-28 22:25:22 +02:00
} catch ( . . . ) { Debug : : log ( LOG , " Rule move failed, rule: {} -> {} " , r - > m_rule , r - > m_value ) ; }
2024-12-16 19:05:24 +01:00
break ;
}
case CWindowRule : : RULE_CENTER : {
auto RESERVEDOFFSET = Vector2D ( ) ;
2025-04-28 22:25:22 +02:00
const auto ARGS = CVarList ( r - > m_rule , 2 , ' ' ) ;
2024-12-16 19:05:24 +01:00
if ( ARGS [ 1 ] = = " 1 " )
2025-04-30 23:45:20 +02:00
RESERVEDOFFSET = ( PMONITOR - > m_reservedTopLeft - PMONITOR - > m_reservedBottomRight ) / 2.f ;
2022-07-30 12:42:27 +02:00
2025-04-28 22:25:22 +02:00
* PWINDOW - > m_realPosition = PMONITOR - > middle ( ) - PWINDOW - > m_realSize - > goal ( ) / 2.f + RESERVEDOFFSET ;
2024-12-16 19:05:24 +01:00
break ;
}
2023-08-11 14:54:16 +00:00
2024-12-16 19:05:24 +01:00
default : break ;
2022-03-24 18:22:01 +01:00
}
}
2022-04-02 20:04:32 +02:00
// set the pseudo size to the GOAL of our current size
// because the windows are animated on RealSize
2025-04-28 22:25:22 +02:00
PWINDOW - > m_pseudoSize = PWINDOW - > m_realSize - > goal ( ) ;
2022-10-01 18:25:02 +01:00
2023-09-21 17:18:26 -04:00
g_pCompositor - > changeWindowZOrder ( PWINDOW , true ) ;
2022-10-24 18:36:31 +01:00
} else {
2022-03-21 15:17:04 +01:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreated ( PWINDOW ) ;
2022-03-24 18:22:01 +01:00
2024-09-08 00:46:16 +01:00
bool setPseudo = false ;
2025-04-28 22:25:22 +02:00
for ( auto const & r : PWINDOW - > m_matchedRules ) {
if ( r - > m_ruleType ! = CWindowRule : : RULE_SIZE )
2024-12-16 19:05:24 +01:00
continue ;
try {
2025-04-28 22:25:22 +02:00
const auto VALUE = r - > m_rule . substr ( r - > m_rule . find ( ' ' ) + 1 ) ;
2024-12-16 19:05:24 +01:00
const auto SIZEXSTR = VALUE . substr ( 0 , VALUE . find ( ' ' ) ) ;
const auto SIZEYSTR = VALUE . substr ( VALUE . find ( ' ' ) + 1 ) ;
2024-10-30 18:58:36 +00:00
2024-12-16 19:05:24 +01:00
const auto MAXSIZE = PWINDOW - > requestedMaxSize ( ) ;
2024-10-30 18:58:36 +00:00
2025-04-30 23:45:20 +02:00
const float SIZEX = SIZEXSTR = = " max " ? std : : clamp ( MAXSIZE . x , MIN_WINDOW_SIZE , PMONITOR - > m_size . x ) : stringToPercentage ( SIZEXSTR , PMONITOR - > m_size . x ) ;
2024-10-30 18:58:36 +00:00
2025-04-30 23:45:20 +02:00
const float SIZEY = SIZEYSTR = = " max " ? std : : clamp ( MAXSIZE . y , MIN_WINDOW_SIZE , PMONITOR - > m_size . y ) : stringToPercentage ( SIZEYSTR , PMONITOR - > m_size . y ) ;
2024-09-08 00:46:16 +01:00
2024-12-16 19:05:24 +01:00
Debug : : log ( LOG , " Rule size (tiled), applying to {} " , PWINDOW ) ;
2024-09-08 00:46:16 +01:00
2025-04-28 22:25:22 +02:00
setPseudo = true ;
PWINDOW - > m_pseudoSize = Vector2D ( SIZEX , SIZEY ) ;
2024-09-08 00:46:16 +01:00
2024-12-16 19:05:24 +01:00
PWINDOW - > setHidden ( false ) ;
2025-04-28 22:25:22 +02:00
} catch ( . . . ) { Debug : : log ( LOG , " Rule size failed, rule: {} -> {} " , r - > m_rule , r - > m_value ) ; }
2024-09-08 00:46:16 +01:00
}
if ( ! setPseudo )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_pseudoSize = PWINDOW - > m_realSize - > goal ( ) - Vector2D ( 10 , 10 ) ;
2022-04-02 20:04:32 +02:00
}
2022-03-24 18:22:01 +01:00
2025-04-22 15:23:29 +02:00
const auto PFOCUSEDWINDOWPREV = g_pCompositor - > m_lastWindow . lock ( ) ;
2022-08-26 00:38:20 +02:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_windowData . allowsInput . valueOrDefault ( ) ) { // if default value wasn't set to false getPriority() would throw an exception
PWINDOW - > m_windowData . noFocus = CWindowOverridableVar ( false , PWINDOW - > m_windowData . allowsInput . getPriority ( ) ) ;
PWINDOW - > m_noInitialFocus = false ;
PWINDOW - > m_X11ShouldntFocus = false ;
2022-08-27 13:01:55 +02:00
}
2022-12-02 20:10:15 +00:00
// check LS focus grab
2023-07-04 12:05:25 +02:00
const auto PFORCEFOCUS = g_pCompositor - > getForceFocus ( ) ;
2025-04-22 15:23:29 +02:00
const auto PLSFROMFOCUS = g_pCompositor - > getLayerSurfaceFromSurface ( g_pCompositor - > m_lastFocus . lock ( ) ) ;
2025-05-04 00:13:29 +02:00
if ( PLSFROMFOCUS & & PLSFROMFOCUS - > m_layerSurface - > m_current . interactivity ! = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_noInitialFocus = true ;
2024-07-31 17:55:52 +00:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_workspace - > m_hasFullscreenWindow & & ! requestedInternalFSMode . has_value ( ) & & ! requestedClientFSMode . has_value ( ) & & ! PWINDOW - > m_isFloating ) {
2024-03-03 18:39:20 +00:00
if ( * PNEWTAKESOVERFS = = 0 )
2025-04-28 22:25:22 +02:00
PWINDOW - > m_noInitialFocus = true ;
2024-07-31 17:55:52 +00:00
else if ( * PNEWTAKESOVERFS = = 1 )
2025-04-28 22:25:22 +02:00
requestedInternalFSMode = PWINDOW - > m_workspace - > m_fullscreenMode ;
2024-03-03 18:39:20 +00:00
else if ( * PNEWTAKESOVERFS = = 2 )
2025-04-28 22:25:22 +02:00
g_pCompositor - > setWindowFullscreenInternal ( PWINDOW - > m_workspace - > getFullscreenWindow ( ) , FSMODE_NONE ) ;
2023-10-02 16:27:32 +01:00
}
2022-12-02 20:10:15 +00:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_windowData . noFocus . valueOrDefault ( ) & & ! PWINDOW - > m_noInitialFocus & &
( ! PWINDOW - > isX11OverrideRedirect ( ) | | ( PWINDOW - > m_isX11 & & PWINDOW - > m_xwaylandSurface - > wantsFocus ( ) ) ) & & ! workspaceSilent & & ( ! PFORCEFOCUS | | PFORCEFOCUS = = PWINDOW ) & &
2024-05-25 22:43:51 +02:00
! g_pInputManager - > isConstrained ( ) ) {
2022-05-14 14:37:57 +02:00
g_pCompositor - > focusWindow ( PWINDOW ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_activeInactiveAlpha - > setValueAndWarp ( * PACTIVEALPHA ) ;
PWINDOW - > m_dimPercent - > setValueAndWarp ( PWINDOW - > m_windowData . noDim . valueOrDefault ( ) ? 0.f : * PDIMSTRENGTH ) ;
2022-08-30 12:46:17 +02:00
} else {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_activeInactiveAlpha - > setValueAndWarp ( * PINACTIVEALPHA ) ;
PWINDOW - > m_dimPercent - > setValueAndWarp ( 0 ) ;
2022-08-30 12:46:17 +02:00
}
2022-03-21 15:17:04 +01:00
2025-04-28 22:25:22 +02:00
if ( requestedClientFSMode . has_value ( ) & & ( PWINDOW - > m_suppressedEvents & SUPPRESS_FULLSCREEN ) )
2024-07-31 17:55:52 +00:00
requestedClientFSMode = ( eFullscreenMode ) ( ( uint8_t ) requestedClientFSMode . value_or ( FSMODE_NONE ) & ~ ( uint8_t ) FSMODE_FULLSCREEN ) ;
2025-04-28 22:25:22 +02:00
if ( requestedClientFSMode . has_value ( ) & & ( PWINDOW - > m_suppressedEvents & SUPPRESS_MAXIMIZE ) )
2024-07-31 17:55:52 +00:00
requestedClientFSMode = ( eFullscreenMode ) ( ( uint8_t ) requestedClientFSMode . value_or ( FSMODE_NONE ) & ~ ( uint8_t ) FSMODE_MAXIMIZED ) ;
2022-06-27 20:11:09 +02:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_noInitialFocus & & ( requestedInternalFSMode . has_value ( ) | | requestedClientFSMode . has_value ( ) | | requestedFSState . has_value ( ) ) ) {
2024-07-31 17:55:52 +00:00
// fix fullscreen on requested (basically do a switcheroo)
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_workspace - > m_hasFullscreenWindow )
g_pCompositor - > setWindowFullscreenInternal ( PWINDOW - > m_workspace - > getFullscreenWindow ( ) , FSMODE_NONE ) ;
2024-07-31 17:55:52 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_realPosition - > warp ( ) ;
PWINDOW - > m_realSize - > warp ( ) ;
2024-07-31 17:55:52 +00:00
if ( requestedFSState . has_value ( ) ) {
2025-04-28 22:25:22 +02:00
PWINDOW - > m_windowData . syncFullscreen = CWindowOverridableVar ( false , PRIORITY_WINDOW_RULE ) ;
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenState ( PWINDOW , requestedFSState . value ( ) ) ;
2025-04-28 22:25:22 +02:00
} else if ( requestedInternalFSMode . has_value ( ) & & requestedClientFSMode . has_value ( ) & & ! PWINDOW - > m_windowData . syncFullscreen . valueOrDefault ( ) )
2024-12-07 18:51:18 +01:00
g_pCompositor - > setWindowFullscreenState ( PWINDOW , SFullscreenState { . internal = requestedInternalFSMode . value ( ) , . client = requestedClientFSMode . value ( ) } ) ;
2024-07-31 17:55:52 +00:00
else if ( requestedInternalFSMode . has_value ( ) )
g_pCompositor - > setWindowFullscreenInternal ( PWINDOW , requestedInternalFSMode . value ( ) ) ;
else if ( requestedClientFSMode . has_value ( ) )
g_pCompositor - > setWindowFullscreenClient ( PWINDOW , requestedClientFSMode . value ( ) ) ;
2022-06-26 12:12:29 +02:00
}
2022-07-06 15:42:37 +02:00
// recheck idle inhibitors
g_pInputManager - > recheckIdleInhibitorStatus ( ) ;
2022-08-06 20:57:38 +02:00
PWINDOW - > updateToplevel ( ) ;
2023-09-02 18:41:02 +00:00
if ( workspaceSilent ) {
2024-04-27 12:43:12 +01:00
if ( validMapped ( PFOCUSEDWINDOWPREV ) ) {
2022-08-26 00:38:20 +02:00
g_pCompositor - > focusWindow ( PFOCUSEDWINDOWPREV ) ;
2022-08-26 01:08:11 +02:00
PFOCUSEDWINDOWPREV - > updateWindowDecos ( ) ; // need to for some reason i cba to find out why
} else if ( ! PFOCUSEDWINDOWPREV )
2022-08-26 00:38:20 +02:00
g_pCompositor - > focusWindow ( nullptr ) ;
}
2024-10-27 00:44:55 +00:00
// swallow
if ( SWALLOWER ) {
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowRemoved ( SWALLOWER ) ;
g_pHyprRenderer - > damageWindow ( SWALLOWER ) ;
SWALLOWER - > setHidden ( true ) ;
2024-10-27 18:45:38 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( PWINDOW - > monitorID ( ) ) ;
2022-10-01 19:19:15 +01:00
}
2025-04-28 22:25:22 +02:00
PWINDOW - > m_firstMap = false ;
2023-05-24 19:23:07 +02:00
2025-04-30 23:45:20 +02:00
Debug : : log ( LOG , " Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j} " , PMONITOR - > m_name , PWINDOW - > m_realPosition - > goal ( ) , PWINDOW - > m_realSize - > goal ( ) ) ;
2022-09-25 20:07:48 +02:00
2025-05-08 22:10:31 +02:00
// emit the hook event here after basic stuff has been initialized
2023-02-19 20:54:53 +00:00
EMIT_HOOK_EVENT ( " openWindow " , PWINDOW ) ;
2022-11-02 15:15:39 +00:00
2023-12-10 16:28:12 +00:00
// apply data from default decos. Borders, shadows.
g_pDecorationPositioner - > forceRecalcFor ( PWINDOW ) ;
PWINDOW - > updateWindowDecos ( ) ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateWindow ( PWINDOW ) ;
// do animations
g_pAnimationManager - > onWindowPostCreateClose ( PWINDOW , false ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_alpha - > setValueAndWarp ( 0.f ) ;
* PWINDOW - > m_alpha = 1.f ;
2023-12-10 16:28:12 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_realPosition - > setCallbackOnEnd ( setVector2DAnimToMove ) ;
PWINDOW - > m_realSize - > setCallbackOnEnd ( setVector2DAnimToMove ) ;
2023-12-10 16:28:12 +00:00
2022-11-02 15:15:39 +00:00
// recalc the values for this window
g_pCompositor - > updateWindowAnimatedDecorationValues ( PWINDOW ) ;
2023-10-02 16:22:39 +01:00
// avoid this window being visible
2025-04-28 22:25:22 +02:00
if ( PWORKSPACE - > m_hasFullscreenWindow & & ! PWINDOW - > isFullscreen ( ) & & ! PWINDOW - > m_isFloating )
PWINDOW - > m_alpha - > setValueAndWarp ( 0.f ) ;
2023-01-20 19:44:30 +01:00
2025-04-30 23:45:20 +02:00
g_pCompositor - > setPreferredScaleForSurface ( PWINDOW - > m_wlSurface - > resource ( ) , PMONITOR - > m_scale ) ;
g_pCompositor - > setPreferredTransformForSurface ( PWINDOW - > m_wlSurface - > resource ( ) , PMONITOR - > m_transform ) ;
2023-11-01 19:50:32 +00:00
2025-05-02 17:07:20 +02:00
if ( g_pSeatManager - > m_mouse . expired ( ) | | ! g_pInputManager - > isConstrained ( ) )
2024-01-30 16:24:41 +00:00
g_pInputManager - > sendMotionEventsToFocused ( ) ;
2023-11-03 22:47:12 +00:00
// fix some xwayland apps that don't behave nicely
2025-04-28 22:25:22 +02:00
PWINDOW - > m_reportedSize = PWINDOW - > m_pendingReportedSize ;
2023-12-23 15:49:42 +01:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_workspace )
PWINDOW - > m_workspace - > updateWindows ( ) ;
2024-03-01 23:04:29 +00:00
2024-08-30 14:12:23 +02:00
if ( PMONITOR & & PWINDOW - > isX11OverrideRedirect ( ) )
2025-04-30 23:45:20 +02:00
PWINDOW - > m_X11SurfaceScaledBy = PMONITOR - > m_scale ;
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events : : listener_unmapWindow ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-03-21 15:17:04 +01:00
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " {:c} unmapped " , PWINDOW ) ;
2022-09-25 20:07:48 +02:00
2024-07-15 21:48:04 +10:00
static auto PEXITRETAINSFS = CConfigValue < Hyprlang : : INT > ( " misc:exit_window_retains_fullscreen " ) ;
2024-07-31 17:55:52 +00:00
const auto CURRENTWINDOWFSSTATE = PWINDOW - > isFullscreen ( ) ;
2025-04-28 22:25:22 +02:00
const auto CURRENTFSMODE = PWINDOW - > m_fullscreenState . internal ;
2024-07-15 21:48:04 +10:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_wlSurface - > exists ( ) | | ! PWINDOW - > m_isMapped ) {
2023-09-20 15:25:03 +00:00
Debug : : log ( WARN , " {} unmapped without being mapped?? " , PWINDOW ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_fadingOut = false ;
2023-03-28 20:17:47 +01:00
return ;
}
2025-04-28 22:25:22 +02:00
const auto PMONITOR = PWINDOW - > m_monitor . lock ( ) ;
2023-11-11 15:18:04 +00:00
if ( PMONITOR ) {
2025-04-30 23:45:20 +02:00
PWINDOW - > m_originalClosedPos = PWINDOW - > m_realPosition - > value ( ) - PMONITOR - > m_position ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_originalClosedSize = PWINDOW - > m_realSize - > value ( ) ;
PWINDOW - > m_originalClosedExtents = PWINDOW - > getFullWindowExtents ( ) ;
2023-11-11 15:18:04 +00:00
}
2023-09-20 15:25:03 +00:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " closewindow " , std : : format ( " {:x} " , PWINDOW ) } ) ;
2023-02-19 20:54:53 +00:00
EMIT_HOOK_EVENT ( " closeWindow " , PWINDOW ) ;
2022-03-24 21:34:24 +01:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_isFloating & & ! PWINDOW - > m_isX11 & &
std : : any_of ( PWINDOW - > m_matchedRules . begin ( ) , PWINDOW - > m_matchedRules . end ( ) , [ ] ( const auto & r ) { return r - > m_ruleType = = CWindowRule : : RULE_PERSISTENTSIZE ; } ) ) {
Debug : : log ( LOG , " storing floating size {}x{} for window {}::{} on close " , PWINDOW - > m_realSize - > value ( ) . x , PWINDOW - > m_realSize - > value ( ) . y , PWINDOW - > m_class ,
PWINDOW - > m_title ) ;
g_pConfigManager - > storeFloatingSize ( PWINDOW , PWINDOW - > m_realSize - > value ( ) ) ;
2025-03-08 08:20:27 -05:00
}
2024-07-27 10:02:02 -05:00
PROTO : : toplevelExport - > onWindowUnmap ( PWINDOW ) ;
2022-12-05 17:05:15 +00:00
2024-07-31 17:55:52 +00:00
if ( PWINDOW - > isFullscreen ( ) )
g_pCompositor - > setWindowFullscreenInternal ( PWINDOW , FSMODE_NONE ) ;
2023-08-09 14:28:04 +02:00
2022-04-24 16:41:01 +02:00
// Allow the renderer to catch the last frame.
2024-12-22 17:12:09 +01:00
g_pHyprRenderer - > makeWindowSnapshot ( PWINDOW ) ;
2022-04-24 16:41:01 +02:00
2022-10-01 19:19:15 +01:00
// swallowing
2025-04-28 22:25:22 +02:00
if ( valid ( PWINDOW - > m_swallowed ) ) {
if ( PWINDOW - > m_swallowed - > m_currentlySwallowed ) {
PWINDOW - > m_swallowed - > m_currentlySwallowed = false ;
PWINDOW - > m_swallowed - > setHidden ( false ) ;
2024-10-27 00:44:55 +00:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_groupData . pNextWindow . lock ( ) )
PWINDOW - > m_swallowed - > m_groupSwallowed = true ; // flag for the swallowed window to be created into the group where it belongs when auto_group = false.
2024-10-27 00:44:55 +00:00
2025-04-28 22:25:22 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreated ( PWINDOW - > m_swallowed . lock ( ) ) ;
2025-02-05 10:56:41 +01:00
}
2024-10-27 00:44:55 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_swallowed - > m_groupSwallowed = false ;
PWINDOW - > m_swallowed . reset ( ) ;
2022-10-01 19:19:15 +01:00
}
2022-08-24 11:14:11 +02:00
bool wasLastWindow = false ;
2025-04-22 15:23:29 +02:00
if ( PWINDOW = = g_pCompositor - > m_lastWindow . lock ( ) ) {
2024-04-27 12:43:12 +01:00
wasLastWindow = true ;
2025-04-22 15:23:29 +02:00
g_pCompositor - > m_lastWindow . reset ( ) ;
g_pCompositor - > m_lastFocus . reset ( ) ;
2023-04-07 12:54:11 +01:00
g_pInputManager - > releaseAllMouseButtons ( ) ;
2022-04-02 18:57:09 +02:00
}
2022-03-21 15:17:04 +01:00
2025-05-01 23:57:11 +02:00
if ( PWINDOW = = g_pInputManager - > m_currentlyDraggedWindow . lock ( ) )
2024-07-27 16:46:19 +00:00
g_pKeybindManager - > changeMouseBindMode ( MBIND_INVALID ) ;
2022-03-21 19:18:33 +01:00
// remove the fullscreen window status from workspace if we closed it
2025-04-28 22:25:22 +02:00
const auto PWORKSPACE = PWINDOW - > m_workspace ;
2022-03-21 19:18:33 +01:00
2025-04-25 02:37:12 +02:00
if ( PWORKSPACE - > m_hasFullscreenWindow & & PWINDOW - > isFullscreen ( ) )
PWORKSPACE - > m_hasFullscreenWindow = false ;
2022-03-21 19:18:33 +01:00
2022-03-21 15:17:04 +01:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowRemoved ( PWINDOW ) ;
2024-10-21 10:09:14 -05:00
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2022-03-22 22:22:59 +01:00
// do this after onWindowRemoved because otherwise it'll think the window is invalid
2025-04-28 22:25:22 +02:00
PWINDOW - > m_isMapped = false ;
2022-03-22 22:22:59 +01:00
2022-08-24 11:14:11 +02:00
// refocus on a new window if needed
if ( wasLastWindow ) {
2024-08-21 18:24:42 +08:00
static auto FOCUSONCLOSE = CConfigValue < Hyprlang : : INT > ( " input:focus_on_close " ) ;
PHLWINDOW PWINDOWCANDIDATE = nullptr ;
if ( * FOCUSONCLOSE )
PWINDOWCANDIDATE = ( g_pCompositor - > vectorToWindowUnified ( g_pInputManager - > getMouseCoordsInternal ( ) , RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING ) ) ;
else
PWINDOWCANDIDATE = g_pLayoutManager - > getCurrentLayout ( ) - > getNextWindowCandidate ( PWINDOW ) ;
2022-08-20 18:12:59 +02:00
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " On closed window, new focused candidate is {} " , PWINDOWCANDIDATE ) ;
2022-08-20 18:12:59 +02:00
2025-04-22 15:23:29 +02:00
if ( PWINDOWCANDIDATE ! = g_pCompositor - > m_lastWindow . lock ( ) & & PWINDOWCANDIDATE ) {
2023-11-01 19:50:32 +00:00
g_pCompositor - > focusWindow ( PWINDOWCANDIDATE ) ;
2024-07-15 21:48:04 +10:00
if ( * PEXITRETAINSFS & & CURRENTWINDOWFSSTATE )
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( PWINDOWCANDIDATE , CURRENTFSMODE ) ;
2024-07-15 21:48:04 +10:00
}
2023-11-01 19:50:32 +00:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOWCANDIDATE & & PWINDOW - > m_workspace & & PWINDOW - > m_workspace - > getWindows ( ) = = 0 )
2024-03-09 18:12:55 +00:00
g_pInputManager - > refocus ( ) ;
2023-12-12 14:58:43 +00:00
g_pInputManager - > sendMotionEventsToFocused ( ) ;
2023-10-06 01:11:47 +01:00
// CWindow::onUnmap will remove this window's active status, but we can't really do it above.
2025-04-22 15:23:29 +02:00
if ( PWINDOW = = g_pCompositor - > m_lastWindow . lock ( ) | | ! g_pCompositor - > m_lastWindow . lock ( ) ) {
2023-10-06 01:11:47 +01:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindow " , " , " } ) ;
2024-05-01 13:57:27 +01:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindowv2 " , " " } ) ;
2024-04-27 12:43:12 +01:00
EMIT_HOOK_EVENT ( " activeWindow " , ( PHLWINDOW ) nullptr ) ;
2022-08-24 11:14:11 +02:00
}
} else {
Debug : : log ( LOG , " Unmapped was not focused, ignoring a refocus. " ) ;
2022-08-23 23:15:04 +02:00
}
2022-08-03 12:03:18 +02:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_fadingOut = true ;
2022-04-05 19:28:10 +02:00
2022-07-25 21:08:54 +02:00
g_pCompositor - > addToFadingOutSafe ( PWINDOW ) ;
2022-04-14 17:00:35 +02:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_X11DoesntWantBorders ) // don't animate out if they weren't animated in.
* PWINDOW - > m_realPosition = PWINDOW - > m_realPosition - > value ( ) + Vector2D ( 0.01f , 0.01f ) ; // it has to be animated, otherwise onWindowPostCreateClose will ignore it
2022-09-25 20:07:48 +02:00
2022-07-28 13:28:43 +02:00
// anims
2022-05-28 18:28:55 +02:00
g_pAnimationManager - > onWindowPostCreateClose ( PWINDOW , true ) ;
2025-04-28 22:25:22 +02:00
* PWINDOW - > m_alpha = 0.f ;
2022-05-29 11:24:42 +02:00
2022-07-06 15:42:37 +02:00
// recheck idle inhibitors
g_pInputManager - > recheckIdleInhibitorStatus ( ) ;
2022-10-22 22:10:34 +01:00
// force report all sizes (QT sometimes has an issue with this)
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > m_workspace )
PWINDOW - > m_workspace - > forceReportSizesToWindows ( ) ;
2022-11-04 15:56:31 +00:00
// update lastwindow after focus
PWINDOW - > onUnmap ( ) ;
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events : : listener_commitWindow ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-04-05 18:29:58 +02:00
2025-05-04 23:39:00 +02:00
if ( ! PWINDOW - > m_isX11 & & PWINDOW - > m_xdgSurface - > m_initialCommit ) {
2024-03-29 00:43:50 +00:00
Vector2D predSize = g_pLayoutManager - > getCurrentLayout ( ) - > predictSizeForNewWindow ( PWINDOW ) ;
2024-02-28 23:14:50 +00:00
Debug : : log ( LOG , " Layout predicts size {} for {} " , predSize , PWINDOW ) ;
2025-05-04 23:39:00 +02:00
PWINDOW - > m_xdgSurface - > m_toplevel - > setSize ( predSize ) ;
2024-02-22 17:33:16 +00:00
return ;
}
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_isMapped | | PWINDOW - > isHidden ( ) )
2022-04-05 18:29:58 +02:00
return ;
2022-03-21 15:17:04 +01:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_reportedSize = PWINDOW - > m_pendingReportedSize ; // apply pending size. We pinged, the window ponged.
2023-10-20 20:15:41 +01:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_isX11 & & ! PWINDOW - > isFullscreen ( ) & & PWINDOW - > m_isFloating ) {
2025-05-04 23:39:00 +02:00
const auto MINSIZE = PWINDOW - > m_xdgSurface - > m_toplevel - > layoutMinSize ( ) ;
const auto MAXSIZE = PWINDOW - > m_xdgSurface - > m_toplevel - > layoutMaxSize ( ) ;
2024-04-03 10:09:42 +01:00
2024-10-07 18:52:49 +00:00
PWINDOW - > clampWindowSize ( MINSIZE , MAXSIZE > Vector2D { 1 , 1 } ? std : : optional < Vector2D > { MAXSIZE } : std : : nullopt ) ;
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2024-04-03 10:09:42 +01:00
}
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_workspace - > m_visible )
2024-04-03 10:09:42 +01:00
return ;
2025-04-28 22:25:22 +02:00
const auto PMONITOR = PWINDOW - > m_monitor . lock ( ) ;
2024-10-12 03:29:51 +03:00
2024-10-19 16:24:03 +01:00
if ( PMONITOR )
2025-05-02 17:07:20 +02:00
PMONITOR - > debugLastPresentation ( g_pSeatManager - > m_isPointerFrameCommit ? " listener_commitWindow skip " : " listener_commitWindow " ) ;
2024-10-19 16:24:03 +01:00
2025-05-02 17:07:20 +02:00
if ( g_pSeatManager - > m_isPointerFrameCommit ) {
g_pSeatManager - > m_isPointerFrameSkipped = false ;
g_pSeatManager - > m_isPointerFrameCommit = false ;
2024-10-12 03:29:51 +03:00
} else
2025-04-28 22:25:22 +02:00
g_pHyprRenderer - > damageSurface ( PWINDOW - > m_wlSurface - > resource ( ) , PWINDOW - > m_realPosition - > goal ( ) . x , PWINDOW - > m_realPosition - > goal ( ) . y ,
PWINDOW - > m_isX11 ? 1.0 / PWINDOW - > m_X11SurfaceScaledBy : 1.0 ) ;
2024-10-12 03:29:51 +03:00
2025-05-02 17:07:20 +02:00
if ( g_pSeatManager - > m_isPointerFrameSkipped ) {
2024-10-12 03:29:51 +03:00
g_pPointerManager - > sendStoredMovement ( ) ;
g_pSeatManager - > sendPointerFrame ( ) ;
2025-05-02 17:07:20 +02:00
g_pSeatManager - > m_isPointerFrameCommit = true ;
2024-10-12 03:29:51 +03:00
}
2022-07-04 15:58:12 +02:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_isX11 ) {
PWINDOW - > m_subsurfaceHead - > recheckDamageForSubsurfaces ( ) ;
PWINDOW - > m_popupHead - > recheckTree ( ) ;
2024-02-29 14:26:02 +00:00
}
2024-02-29 00:03:28 +00:00
2024-03-05 00:21:37 +00:00
// tearing: if solitary, redraw it. This still might be a single surface window
2025-05-03 16:02:49 +02:00
if ( PMONITOR & & PMONITOR - > m_solitaryClient . lock ( ) = = PWINDOW & & PWINDOW - > canBeTorn ( ) & & PMONITOR - > m_tearingState . canTear & &
PWINDOW - > m_wlSurface - > resource ( ) - > m_current . texture ) {
CRegion damageBox { PWINDOW - > m_wlSurface - > resource ( ) - > m_current . accumulateBufferDamage ( ) } ;
2024-03-05 00:21:37 +00:00
if ( ! damageBox . empty ( ) ) {
2025-04-30 23:45:20 +02:00
if ( PMONITOR - > m_tearingState . busy ) {
PMONITOR - > m_tearingState . frameScheduledWhileBusy = true ;
2024-03-05 00:21:37 +00:00
} else {
2025-04-30 23:45:20 +02:00
PMONITOR - > m_tearingState . nextRenderTorn = true ;
2024-03-05 00:21:37 +00:00
g_pHyprRenderer - > renderMonitor ( PMONITOR ) ;
}
}
}
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events : : listener_destroyWindow ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-03-21 15:17:04 +01:00
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " {:c} destroyed, queueing. " , PWINDOW ) ;
2022-06-28 12:43:08 +02:00
2025-04-22 15:23:29 +02:00
if ( PWINDOW = = g_pCompositor - > m_lastWindow . lock ( ) ) {
g_pCompositor - > m_lastWindow . reset ( ) ;
g_pCompositor - > m_lastFocus . reset ( ) ;
2022-04-02 18:57:09 +02:00
}
2022-03-21 15:17:04 +01:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_wlSurface - > unassign ( ) ;
2024-03-23 22:10:37 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_listeners = { } ;
2024-05-10 23:28:33 +01:00
2022-04-10 16:19:49 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowRemoved ( PWINDOW ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_readyToDelete = true ;
2022-12-16 17:17:31 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_xdgSurface . reset ( ) ;
2024-02-29 17:23:44 +00:00
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_fadingOut ) {
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " Unmapped {} removed instantly " , PWINDOW ) ;
2023-11-01 18:53:36 +00:00
g_pCompositor - > removeWindowFromVectorSafe ( PWINDOW ) ; // most likely X11 unmanaged or sumn
2022-12-07 14:32:24 +00:00
}
2024-08-02 00:31:44 +02:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_listeners . unmap . reset ( ) ;
PWINDOW - > m_listeners . destroy . reset ( ) ;
PWINDOW - > m_listeners . map . reset ( ) ;
PWINDOW - > m_listeners . commit . reset ( ) ;
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events : : listener_activateX11 ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-10-22 16:43:47 +01:00
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " X11 Activate request for window {} " , PWINDOW ) ;
2022-10-22 16:43:47 +01:00
2024-08-30 14:12:23 +02:00
if ( PWINDOW - > isX11OverrideRedirect ( ) ) {
2023-02-03 21:21:14 +00:00
2023-09-20 15:25:03 +00:00
Debug : : log ( LOG , " Unmanaged X11 {} requests activate " , PWINDOW ) ;
2023-02-03 21:21:14 +00:00
2025-04-22 15:23:29 +02:00
if ( g_pCompositor - > m_lastWindow . lock ( ) & & g_pCompositor - > m_lastWindow - > getPID ( ) ! = PWINDOW - > getPID ( ) )
2023-02-03 21:21:14 +00:00
return ;
2025-04-28 22:25:22 +02:00
if ( ! PWINDOW - > m_xwaylandSurface - > wantsFocus ( ) )
2024-02-17 02:47:01 +00:00
return ;
2023-02-03 21:21:14 +00:00
g_pCompositor - > focusWindow ( PWINDOW ) ;
return ;
}
2025-04-28 22:25:22 +02:00
if ( PWINDOW = = g_pCompositor - > m_lastWindow . lock ( ) | | ( PWINDOW - > m_suppressedEvents & SUPPRESS_ACTIVATE ) )
2023-01-29 16:20:53 +00:00
return ;
2024-04-25 00:58:40 +01:00
PWINDOW - > activate ( ) ;
2022-03-21 15:17:04 +01:00
}
2022-07-08 11:24:07 +02:00
void Events : : listener_unmanagedSetGeometry ( void * owner , void * data ) {
2025-04-28 22:25:22 +02:00
PHLWINDOW PWINDOW = ( ( CWindow * ) owner ) - > m_self . lock ( ) ;
2022-07-08 11:24:07 +02:00
2025-05-07 15:21:44 +02:00
if ( ! PWINDOW - > m_isMapped | | ! PWINDOW - > m_xwaylandSurface | | ! PWINDOW - > m_xwaylandSurface - > m_overrideRedirect )
2022-07-08 11:24:07 +02:00
return ;
2025-04-28 22:25:22 +02:00
const auto POS = PWINDOW - > m_realPosition - > goal ( ) ;
const auto SIZ = PWINDOW - > m_realSize - > goal ( ) ;
2022-07-08 11:24:07 +02:00
2025-05-07 15:21:44 +02:00
if ( PWINDOW - > m_xwaylandSurface - > m_geometry . size ( ) > Vector2D { 1 , 1 } )
2022-10-14 20:46:32 +01:00
PWINDOW - > setHidden ( false ) ;
2022-07-28 15:40:06 +02:00
else
2022-10-14 20:46:32 +01:00
PWINDOW - > setHidden ( true ) ;
2022-07-28 15:40:06 +02:00
2025-04-28 22:25:22 +02:00
if ( PWINDOW - > isFullscreen ( ) | | ! PWINDOW - > m_isFloating ) {
2025-02-06 11:21:04 +00:00
PWINDOW - > sendWindowSize ( true ) ;
2022-11-04 15:56:31 +00:00
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
return ;
}
2024-03-03 18:39:20 +00:00
static auto PXWLFORCESCALEZERO = CConfigValue < Hyprlang : : INT > ( " xwayland:force_zero_scaling " ) ;
2023-06-22 21:43:31 +02:00
2025-05-07 15:21:44 +02:00
const auto LOGICALPOS = g_pXWaylandManager - > xwaylandToWaylandCoords ( PWINDOW - > m_xwaylandSurface - > m_geometry . pos ( ) ) ;
2023-08-21 00:39:39 +02:00
2025-05-07 15:21:44 +02:00
if ( abs ( std : : floor ( POS . x ) - LOGICALPOS . x ) > 2 | | abs ( std : : floor ( POS . y ) - LOGICALPOS . y ) > 2 | | abs ( std : : floor ( SIZ . x ) - PWINDOW - > m_xwaylandSurface - > m_geometry . width ) > 2 | |
abs ( std : : floor ( SIZ . y ) - PWINDOW - > m_xwaylandSurface - > m_geometry . height ) > 2 ) {
Debug : : log ( LOG , " Unmanaged window {} requests geometry update to {:j} {:j} " , PWINDOW , LOGICALPOS , PWINDOW - > m_xwaylandSurface - > m_geometry . size ( ) ) ;
2022-09-25 20:07:48 +02:00
2022-07-08 11:24:07 +02:00
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2025-04-28 22:25:22 +02:00
PWINDOW - > m_realPosition - > setValueAndWarp ( Vector2D ( LOGICALPOS . x , LOGICALPOS . y ) ) ;
2022-07-12 14:14:12 +02:00
2025-05-07 15:21:44 +02:00
if ( abs ( std : : floor ( SIZ . x ) - PWINDOW - > m_xwaylandSurface - > m_geometry . w ) > 2 | | abs ( std : : floor ( SIZ . y ) - PWINDOW - > m_xwaylandSurface - > m_geometry . h ) > 2 )
PWINDOW - > m_realSize - > setValueAndWarp ( PWINDOW - > m_xwaylandSurface - > m_geometry . size ( ) ) ;
2022-07-19 16:21:35 +02:00
2024-03-03 18:39:20 +00:00
if ( * PXWLFORCESCALEZERO ) {
2025-04-28 22:25:22 +02:00
if ( const auto PMONITOR = PWINDOW - > m_monitor . lock ( ) ; PMONITOR ) {
2025-04-30 23:45:20 +02:00
PWINDOW - > m_realSize - > setValueAndWarp ( PWINDOW - > m_realSize - > goal ( ) / PMONITOR - > m_scale ) ;
2023-11-10 23:49:23 +00:00
}
2023-06-22 21:43:31 +02:00
}
2025-04-28 22:25:22 +02:00
PWINDOW - > m_position = PWINDOW - > m_realPosition - > goal ( ) ;
PWINDOW - > m_size = PWINDOW - > m_realSize - > goal ( ) ;
2023-06-22 21:43:31 +02:00
2025-04-30 23:45:20 +02:00
PWINDOW - > m_workspace = g_pCompositor - > getMonitorFromVector ( PWINDOW - > m_realPosition - > value ( ) + PWINDOW - > m_realSize - > value ( ) / 2.f ) - > m_activeWorkspace ;
2022-07-19 16:21:35 +02:00
2023-09-21 17:18:26 -04:00
g_pCompositor - > changeWindowZOrder ( PWINDOW , true ) ;
2022-07-11 19:07:59 +02:00
PWINDOW - > updateWindowDecos ( ) ;
2022-07-08 11:24:07 +02:00
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2023-12-17 14:53:48 +00:00
2025-04-28 22:25:22 +02:00
PWINDOW - > m_reportedPosition = PWINDOW - > m_realPosition - > goal ( ) ;
PWINDOW - > m_pendingReportedSize = PWINDOW - > m_realSize - > goal ( ) ;
2022-07-08 11:24:07 +02:00
}
}