2022-06-30 12:09:05 +02:00
# include "IHyprLayout.hpp"
# include "../defines.hpp"
# include "../Compositor.hpp"
2023-11-19 12:29:01 +00:00
# include "../render/decorations/CHyprGroupBarDecoration.hpp"
2024-03-03 18:39:20 +00:00
# include "../config/ConfigValue.hpp"
2024-03-20 01:44:51 +00:00
# include "../desktop/Window.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-05-25 22:43:51 +02:00
# include "../xwayland/XSurface.hpp"
2022-06-30 12:09:05 +02:00
2024-04-27 12:43:12 +01:00
void IHyprLayout : : onWindowCreated ( PHLWINDOW pWindow , eDirection direction ) {
2024-10-02 11:22:19 +02:00
CBox desiredGeometry = { } ;
g_pXWaylandManager - > getGeometryForWindow ( pWindow , & desiredGeometry ) ;
2022-08-05 17:52:14 +02:00
2024-10-02 11:22:19 +02:00
if ( desiredGeometry . width < = 5 | | desiredGeometry . height < = 5 ) {
2024-10-27 18:45:38 +00:00
const auto PMONITOR = pWindow - > m_pMonitor . lock ( ) ;
2024-10-02 11:22:19 +02:00
pWindow - > m_vLastFloatingSize = PMONITOR - > vecSize / 2.f ;
} else
pWindow - > m_vLastFloatingSize = Vector2D ( desiredGeometry . width , desiredGeometry . height ) ;
2022-08-05 17:52:14 +02:00
2024-10-02 11:22:19 +02:00
pWindow - > m_vPseudoSize = pWindow - > m_vLastFloatingSize ;
2023-06-30 11:29:02 +02:00
2024-10-02 11:22:19 +02:00
bool autoGrouped = IHyprLayout : : onWindowCreatedAutoGroup ( pWindow ) ;
if ( autoGrouped )
return ;
if ( pWindow - > m_bIsFloating )
onWindowCreatedFloating ( pWindow ) ;
else
2023-09-13 10:13:29 +00:00
onWindowCreatedTiling ( pWindow , direction ) ;
2024-12-19 19:22:40 +00:00
if ( ! g_pXWaylandManager - > shouldBeFloated ( pWindow ) ) // do not apply group rules to child windows
pWindow - > applyGroupRules ( ) ;
2022-06-30 12:09:05 +02:00
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : onWindowRemoved ( PHLWINDOW pWindow ) {
2024-07-31 17:55:52 +00:00
if ( pWindow - > isFullscreen ( ) )
g_pCompositor - > setWindowFullscreenInternal ( pWindow , FSMODE_NONE ) ;
2022-12-07 18:55:56 +00:00
2024-04-27 12:43:12 +01:00
if ( ! pWindow - > m_sGroupData . pNextWindow . expired ( ) ) {
if ( pWindow - > m_sGroupData . pNextWindow . lock ( ) = = pWindow )
pWindow - > m_sGroupData . pNextWindow . reset ( ) ;
2023-02-19 21:07:32 +00:00
else {
// find last window and update
2024-04-27 12:43:12 +01:00
PHLWINDOW PWINDOWPREV = pWindow - > getGroupPrevious ( ) ;
2023-09-04 13:13:39 +00:00
const auto WINDOWISVISIBLE = pWindow - > getGroupCurrent ( ) = = pWindow ;
2023-02-19 21:07:32 +00:00
2023-09-04 13:13:39 +00:00
if ( WINDOWISVISIBLE )
2024-04-27 12:43:12 +01:00
PWINDOWPREV - > setGroupCurrent ( pWindow - > m_sGroupData . head ? pWindow - > m_sGroupData . pNextWindow . lock ( ) : PWINDOWPREV ) ;
2023-02-19 21:07:32 +00:00
2023-09-04 13:13:39 +00:00
PWINDOWPREV - > m_sGroupData . pNextWindow = pWindow - > m_sGroupData . pNextWindow ;
2023-02-19 21:07:32 +00:00
2024-04-27 12:43:12 +01:00
pWindow - > m_sGroupData . pNextWindow . reset ( ) ;
2023-02-19 21:07:32 +00:00
if ( pWindow - > m_sGroupData . head ) {
2024-05-05 17:16:00 +01:00
std : : swap ( PWINDOWPREV - > m_sGroupData . pNextWindow - > m_sGroupData . head , pWindow - > m_sGroupData . head ) ;
std : : swap ( PWINDOWPREV - > m_sGroupData . pNextWindow - > m_sGroupData . locked , pWindow - > m_sGroupData . locked ) ;
2023-02-19 21:07:32 +00:00
}
2024-05-05 17:16:00 +01:00
if ( pWindow = = m_pLastTiledWindow )
2024-04-27 12:43:12 +01:00
m_pLastTiledWindow . reset ( ) ;
2023-02-19 21:07:32 +00:00
2023-02-19 23:26:36 +00:00
pWindow - > setHidden ( false ) ;
2023-08-30 15:39:22 +00:00
pWindow - > updateWindowDecos ( ) ;
2023-09-04 13:13:39 +00:00
PWINDOWPREV - > getGroupCurrent ( ) - > updateWindowDecos ( ) ;
2023-08-30 15:39:22 +00:00
g_pCompositor - > updateWindowAnimatedDecorationValues ( pWindow ) ;
2023-02-19 21:07:32 +00:00
return ;
}
}
2022-06-30 12:09:05 +02:00
if ( pWindow - > m_bIsFloating ) {
onWindowRemovedFloating ( pWindow ) ;
} else {
onWindowRemovedTiling ( pWindow ) ;
}
2022-10-24 12:25:36 +01:00
2024-05-05 17:16:00 +01:00
if ( pWindow = = m_pLastTiledWindow )
2024-04-27 12:43:12 +01:00
m_pLastTiledWindow . reset ( ) ;
2022-06-30 12:09:05 +02:00
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : onWindowRemovedFloating ( PHLWINDOW pWindow ) {
2024-12-07 18:51:18 +01:00
; // no-op
2022-06-30 12:09:05 +02:00
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : onWindowCreatedFloating ( PHLWINDOW pWindow ) {
2023-08-17 08:13:19 +00:00
2023-11-04 17:03:05 +00:00
CBox desiredGeometry = { 0 } ;
2022-06-30 12:09:05 +02:00
g_pXWaylandManager - > getGeometryForWindow ( pWindow , & desiredGeometry ) ;
2024-10-27 18:45:38 +00:00
const auto PMONITOR = pWindow - > m_pMonitor . lock ( ) ;
2023-08-15 20:09:32 +02:00
if ( pWindow - > m_bIsX11 ) {
Vector2D xy = { desiredGeometry . x , desiredGeometry . y } ;
xy = g_pXWaylandManager - > xwaylandToWaylandCoords ( xy ) ;
desiredGeometry . x = xy . x ;
desiredGeometry . y = xy . y ;
}
2023-06-22 21:43:31 +02:00
2024-03-03 18:39:20 +00:00
static auto PXWLFORCESCALEZERO = CConfigValue < Hyprlang : : INT > ( " xwayland:force_zero_scaling " ) ;
2022-06-30 12:09:05 +02:00
if ( ! PMONITOR ) {
2023-09-20 15:25:03 +00:00
Debug : : log ( ERR , " {:m} has an invalid monitor in onWindowCreatedFloating!!! " , pWindow ) ;
2022-06-30 12:09:05 +02:00
return ;
}
2022-07-18 13:14:31 +02:00
if ( desiredGeometry . width < = 5 | | desiredGeometry . height < = 5 ) {
2024-06-08 10:07:59 +02:00
const auto PWINDOWSURFACE = pWindow - > m_pWLSurface - > resource ( ) ;
pWindow - > m_vRealSize = PWINDOWSURFACE - > current . size ;
2022-07-28 15:40:06 +02:00
2022-12-16 17:17:31 +00:00
if ( ( desiredGeometry . width < = 1 | | desiredGeometry . height < = 1 ) & & pWindow - > m_bIsX11 & &
2024-08-30 14:12:23 +02:00
pWindow - > isX11OverrideRedirect ( ) ) { // XDG windows should be fine. TODO: check for weird atoms?
2022-10-14 20:46:32 +01:00
pWindow - > setHidden ( true ) ;
2022-07-28 15:40:06 +02:00
return ;
}
2022-09-25 20:07:48 +02:00
2022-07-18 13:14:31 +02:00
// reject any windows with size <= 5x5
2024-03-02 01:35:17 +01:00
if ( pWindow - > m_vRealSize . goal ( ) . x < = 5 | | pWindow - > m_vRealSize . goal ( ) . y < = 5 )
2022-07-18 13:14:31 +02:00
pWindow - > m_vRealSize = PMONITOR - > vecSize / 2.f ;
2022-06-30 12:09:05 +02:00
2024-08-30 14:12:23 +02:00
if ( pWindow - > m_bIsX11 & & pWindow - > isX11OverrideRedirect ( ) ) {
2023-02-03 21:09:11 +00:00
2024-05-25 22:43:51 +02:00
if ( pWindow - > m_pXWaylandSurface - > geometry . x ! = 0 & & pWindow - > m_pXWaylandSurface - > geometry . y ! = 0 )
pWindow - > m_vRealPosition = g_pXWaylandManager - > xwaylandToWaylandCoords ( pWindow - > m_pXWaylandSurface - > geometry . pos ( ) ) ;
2023-02-03 21:09:11 +00:00
else
2024-03-02 01:35:17 +01:00
pWindow - > m_vRealPosition = Vector2D ( PMONITOR - > vecPosition . x + ( PMONITOR - > vecSize . x - pWindow - > m_vRealSize . goal ( ) . x ) / 2.f ,
PMONITOR - > vecPosition . y + ( PMONITOR - > vecSize . y - pWindow - > m_vRealSize . goal ( ) . y ) / 2.f ) ;
2023-02-03 21:09:11 +00:00
} else {
2024-03-02 01:35:17 +01:00
pWindow - > m_vRealPosition = Vector2D ( PMONITOR - > vecPosition . x + ( PMONITOR - > vecSize . x - pWindow - > m_vRealSize . goal ( ) . x ) / 2.f ,
PMONITOR - > vecPosition . y + ( PMONITOR - > vecSize . y - pWindow - > m_vRealSize . goal ( ) . y ) / 2.f ) ;
2023-02-03 21:09:11 +00:00
}
2022-06-30 12:09:05 +02:00
} else {
// we respect the size.
pWindow - > m_vRealSize = Vector2D ( desiredGeometry . width , desiredGeometry . height ) ;
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D ( desiredGeometry . x , desiredGeometry . y ) + Vector2D ( desiredGeometry . width , desiredGeometry . height ) / 2.f ;
2022-09-13 22:23:48 +02:00
// check if it's visible on any monitor (only for XDG)
bool visible = pWindow - > m_bIsX11 ;
2022-09-13 12:29:56 +02:00
2023-08-25 18:10:12 +02:00
if ( ! visible ) {
visible = g_pCompositor - > isPointOnAnyMonitor ( Vector2D ( desiredGeometry . x , desiredGeometry . y ) ) & &
g_pCompositor - > isPointOnAnyMonitor ( Vector2D ( desiredGeometry . x + desiredGeometry . width , desiredGeometry . y ) ) & &
g_pCompositor - > isPointOnAnyMonitor ( Vector2D ( desiredGeometry . x , desiredGeometry . y + desiredGeometry . height ) ) & &
g_pCompositor - > isPointOnAnyMonitor ( Vector2D ( desiredGeometry . x + desiredGeometry . width , desiredGeometry . y + desiredGeometry . height ) ) ;
2022-09-13 12:29:56 +02:00
}
2022-06-30 12:09:05 +02:00
// TODO: detect a popup in a more consistent way.
2023-09-03 13:07:40 +02:00
if ( ( desiredGeometry . x = = 0 & & desiredGeometry . y = = 0 ) | | ! visible | | ! pWindow - > m_bIsX11 ) {
2024-05-10 23:28:33 +01:00
// if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available
if ( ! pWindow - > m_bIsX11 & & pWindow - > m_pXDGSurface - > toplevel - > parent & & validMapped ( pWindow - > m_pXDGSurface - > toplevel - > parent - > window ) )
pWindow - > m_vRealPosition = pWindow - > m_pXDGSurface - > toplevel - > parent - > window - > m_vRealPosition . goal ( ) +
pWindow - > m_pXDGSurface - > toplevel - > parent - > window - > m_vRealSize . goal ( ) / 2.F - desiredGeometry . size ( ) / 2.F ;
else
2024-06-02 23:05:02 +02:00
pWindow - > m_vRealPosition = PMONITOR - > vecPosition + PMONITOR - > vecSize / 2.F - desiredGeometry . size ( ) / 2.F ;
2022-06-30 12:09:05 +02:00
} else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups
2023-07-01 16:28:17 +02:00
if ( const auto POPENMON = g_pCompositor - > getMonitorFromVector ( middlePoint ) ; POPENMON - > ID ! = PMONITOR - > ID )
2022-06-30 12:09:05 +02:00
pWindow - > m_vRealPosition = Vector2D ( desiredGeometry . x , desiredGeometry . y ) - POPENMON - > vecPosition + PMONITOR - > vecPosition ;
2023-07-01 16:28:17 +02:00
else
2022-06-30 12:09:05 +02:00
pWindow - > m_vRealPosition = Vector2D ( desiredGeometry . x , desiredGeometry . y ) ;
}
}
2024-03-03 18:39:20 +00:00
if ( * PXWLFORCESCALEZERO & & pWindow - > m_bIsX11 )
2024-03-02 01:35:17 +01:00
pWindow - > m_vRealSize = pWindow - > m_vRealSize . goal ( ) / PMONITOR - > scale ;
2023-06-22 21:43:31 +02:00
2024-08-30 14:12:23 +02:00
if ( pWindow - > m_bX11DoesntWantBorders | | ( pWindow - > m_bIsX11 & & pWindow - > isX11OverrideRedirect ( ) ) ) {
2023-07-20 20:03:23 +02:00
pWindow - > m_vRealPosition . warp ( ) ;
pWindow - > m_vRealSize . warp ( ) ;
2022-06-30 12:09:05 +02:00
}
2024-08-30 14:12:23 +02:00
if ( ! pWindow - > isX11OverrideRedirect ( ) ) {
2024-03-02 01:35:17 +01:00
g_pXWaylandManager - > setWindowSize ( pWindow , pWindow - > m_vRealSize . goal ( ) ) ;
2022-06-30 12:09:05 +02:00
2023-09-21 17:18:26 -04:00
g_pCompositor - > changeWindowZOrder ( pWindow , true ) ;
2023-11-09 22:43:52 +00:00
} else {
2024-03-02 01:35:17 +01:00
pWindow - > m_vPendingReportedSize = pWindow - > m_vRealSize . goal ( ) ;
2023-11-09 22:43:52 +00:00
pWindow - > m_vReportedSize = pWindow - > m_vPendingReportedSize ;
}
2022-06-30 12:09:05 +02:00
}
2024-10-02 11:22:19 +02:00
bool IHyprLayout : : onWindowCreatedAutoGroup ( PHLWINDOW pWindow ) {
2024-10-27 00:44:55 +00:00
static auto PAUTOGROUP = CConfigValue < Hyprlang : : INT > ( " group:auto_group " ) ;
const PHLWINDOW OPENINGON = g_pCompositor - > m_pLastWindow . lock ( ) & & g_pCompositor - > m_pLastWindow - > m_pWorkspace = = pWindow - > m_pWorkspace ?
g_pCompositor - > m_pLastWindow . lock ( ) :
2024-11-22 16:01:02 +00:00
( pWindow - > m_pWorkspace ? pWindow - > m_pWorkspace - > getFirstWindow ( ) : nullptr ) ;
2024-10-27 00:44:55 +00:00
const bool FLOATEDINTOTILED = pWindow - > m_bIsFloating & & ! OPENINGON - > m_bIsFloating ;
const bool SWALLOWING = pWindow - > m_pSwallowed | | pWindow - > m_bGroupSwallowed ;
if ( ( * PAUTOGROUP | | SWALLOWING ) // continue if auto_group is enabled or if dealing with window swallowing.
2024-10-22 23:51:25 +00:00
& & OPENINGON // this shouldn't be 0, but honestly, better safe than sorry.
2024-10-16 21:13:35 +00:00
& & OPENINGON ! = pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group.
2024-10-22 23:51:25 +00:00
& & OPENINGON - > m_sGroupData . pNextWindow . lock ( ) // check if OPENINGON is a group.
2024-10-13 23:25:19 +00:00
& & pWindow - > canBeGroupedInto ( OPENINGON ) // check if the new window can be grouped into OPENINGON.
2024-10-27 00:44:55 +00:00
& & ! g_pXWaylandManager - > shouldBeFloated ( pWindow ) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !FLOATEDINTOTILED.
& & ! FLOATEDINTOTILED ) { // don't group a new floated window into a tiled group (for convenience).
2024-10-02 11:22:19 +02:00
2024-10-14 18:31:17 +00:00
pWindow - > m_bIsFloating = OPENINGON - > m_bIsFloating ; // match the floating state. Needed to autogroup a new tiled window into a floated group.
2024-10-02 11:22:19 +02:00
static auto USECURRPOS = CConfigValue < Hyprlang : : INT > ( " group:insert_after_current " ) ;
2024-10-07 14:22:55 +02:00
( * USECURRPOS ? OPENINGON : OPENINGON - > getGroupTail ( ) ) - > insertWindowToGroup ( pWindow ) ;
2024-10-02 11:22:19 +02:00
2024-10-07 14:22:55 +02:00
OPENINGON - > setGroupCurrent ( pWindow ) ;
2024-12-21 16:35:47 +00:00
pWindow - > applyGroupRules ( ) ;
2024-10-02 11:22:19 +02:00
pWindow - > updateWindowDecos ( ) ;
recalculateWindow ( pWindow ) ;
if ( ! pWindow - > getDecorationByType ( DECORATION_GROUPBAR ) )
pWindow - > addWindowDeco ( std : : make_unique < CHyprGroupBarDecoration > ( pWindow ) ) ;
return true ;
}
return false ;
}
2022-06-30 12:09:05 +02:00
void IHyprLayout : : onBeginDragWindow ( ) {
2024-04-27 12:43:12 +01:00
const auto DRAGGINGWINDOW = g_pInputManager - > currentlyDraggedWindow . lock ( ) ;
2022-06-30 12:09:05 +02:00
2024-03-06 03:15:44 +03:00
m_iMouseMoveEventCount = 1 ;
m_vBeginDragSizeXY = Vector2D ( ) ;
2022-06-30 12:09:05 +02:00
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
2024-04-27 12:43:12 +01:00
if ( ! validMapped ( DRAGGINGWINDOW ) ) {
2022-06-30 12:09:05 +02:00
Debug : : log ( ERR , " Dragging attempted on an invalid window! " ) ;
2024-07-27 16:46:19 +00:00
g_pKeybindManager - > changeMouseBindMode ( MBIND_INVALID ) ;
2022-06-30 12:09:05 +02:00
return ;
}
2024-07-31 17:55:52 +00:00
if ( DRAGGINGWINDOW - > isFullscreen ( ) ) {
2023-08-28 22:54:23 +02:00
Debug : : log ( LOG , " Dragging a fullscreen window " ) ;
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( DRAGGINGWINDOW , FSMODE_NONE ) ;
2022-06-30 12:09:05 +02:00
}
2024-04-02 20:32:39 +01:00
const auto PWORKSPACE = DRAGGINGWINDOW - > m_pWorkspace ;
2022-06-30 12:09:05 +02:00
2022-12-08 17:45:25 +00:00
if ( PWORKSPACE - > m_bHasFullscreenWindow & & ( ! DRAGGINGWINDOW - > m_bCreatedOverFullscreen | | ! DRAGGINGWINDOW - > m_bIsFloating ) ) {
Debug : : log ( LOG , " Rejecting drag on a fullscreen workspace. (window under fullscreen) " ) ;
2024-07-27 16:46:19 +00:00
g_pKeybindManager - > changeMouseBindMode ( MBIND_INVALID ) ;
2022-06-30 12:09:05 +02:00
return ;
}
DRAGGINGWINDOW - > m_bDraggingTiled = false ;
2023-05-29 18:05:41 +02:00
m_vDraggingWindowOriginalFloatSize = DRAGGINGWINDOW - > m_vLastFloatingSize ;
2022-06-30 12:09:05 +02:00
if ( ! DRAGGINGWINDOW - > m_bIsFloating ) {
2022-09-19 19:04:48 +01:00
if ( g_pInputManager - > dragMode = = MBIND_MOVE ) {
2024-03-02 01:35:17 +01:00
DRAGGINGWINDOW - > m_vLastFloatingSize = ( DRAGGINGWINDOW - > m_vRealSize . goal ( ) * 0.8489 ) . clamp ( Vector2D { 5 , 5 } , Vector2D { } ) . floor ( ) ;
2022-06-30 12:09:05 +02:00
changeWindowFloatingMode ( DRAGGINGWINDOW ) ;
2022-12-16 17:17:31 +00:00
DRAGGINGWINDOW - > m_bIsFloating = true ;
2022-06-30 12:09:05 +02:00
DRAGGINGWINDOW - > m_bDraggingTiled = true ;
2022-08-05 17:52:14 +02:00
2024-03-02 01:35:17 +01:00
DRAGGINGWINDOW - > m_vRealPosition = g_pInputManager - > getMouseCoordsInternal ( ) - DRAGGINGWINDOW - > m_vRealSize . goal ( ) / 2.f ;
2022-06-30 12:09:05 +02:00
}
}
2022-12-16 17:17:31 +00:00
m_vBeginDragXY = g_pInputManager - > getMouseCoordsInternal ( ) ;
2024-03-02 01:35:17 +01:00
m_vBeginDragPositionXY = DRAGGINGWINDOW - > m_vRealPosition . goal ( ) ;
m_vBeginDragSizeXY = DRAGGINGWINDOW - > m_vRealSize . goal ( ) ;
2022-12-16 17:17:31 +00:00
m_vLastDragXY = m_vBeginDragXY ;
2022-06-30 12:09:05 +02:00
2022-10-03 22:41:05 +01:00
// get the grab corner
2024-03-12 22:43:22 -04:00
static auto RESIZECORNER = CConfigValue < Hyprlang : : INT > ( " general:resize_corner " ) ;
2024-03-12 23:38:32 -04:00
if ( * RESIZECORNER ! = 0 & & * RESIZECORNER < = 4 & & DRAGGINGWINDOW - > m_bIsFloating ) {
2024-03-12 22:43:22 -04:00
switch ( * RESIZECORNER ) {
case 1 :
m_eGrabbedCorner = CORNER_TOPLEFT ;
g_pInputManager - > setCursorImageUntilUnset ( " nw-resize " ) ;
break ;
case 2 :
m_eGrabbedCorner = CORNER_TOPRIGHT ;
g_pInputManager - > setCursorImageUntilUnset ( " ne-resize " ) ;
break ;
case 3 :
m_eGrabbedCorner = CORNER_BOTTOMRIGHT ;
g_pInputManager - > setCursorImageUntilUnset ( " se-resize " ) ;
break ;
case 4 :
m_eGrabbedCorner = CORNER_BOTTOMLEFT ;
g_pInputManager - > setCursorImageUntilUnset ( " sw-resize " ) ;
break ;
}
} else if ( m_vBeginDragXY . x < m_vBeginDragPositionXY . x + m_vBeginDragSizeXY . x / 2.0 ) {
2023-02-26 03:56:23 +02:00
if ( m_vBeginDragXY . y < m_vBeginDragPositionXY . y + m_vBeginDragSizeXY . y / 2.0 ) {
2023-02-12 22:24:47 +00:00
m_eGrabbedCorner = CORNER_TOPLEFT ;
2023-02-26 03:56:23 +02:00
g_pInputManager - > setCursorImageUntilUnset ( " nw-resize " ) ;
} else {
2023-02-12 22:24:47 +00:00
m_eGrabbedCorner = CORNER_BOTTOMLEFT ;
2023-02-26 03:56:23 +02:00
g_pInputManager - > setCursorImageUntilUnset ( " sw-resize " ) ;
}
2022-10-03 22:41:05 +01:00
} else {
2023-02-26 03:56:23 +02:00
if ( m_vBeginDragXY . y < m_vBeginDragPositionXY . y + m_vBeginDragSizeXY . y / 2.0 ) {
2023-02-12 22:24:47 +00:00
m_eGrabbedCorner = CORNER_TOPRIGHT ;
2023-02-26 03:56:23 +02:00
g_pInputManager - > setCursorImageUntilUnset ( " ne-resize " ) ;
} else {
2023-02-12 22:24:47 +00:00
m_eGrabbedCorner = CORNER_BOTTOMRIGHT ;
2023-02-26 03:56:23 +02:00
g_pInputManager - > setCursorImageUntilUnset ( " se-resize " ) ;
}
2022-10-03 22:41:05 +01:00
}
2023-08-08 16:52:20 +00:00
if ( g_pInputManager - > dragMode ! = MBIND_RESIZE & & g_pInputManager - > dragMode ! = MBIND_RESIZE_FORCE_RATIO & & g_pInputManager - > dragMode ! = MBIND_RESIZE_BLOCK_RATIO )
2023-02-26 23:08:20 +00:00
g_pInputManager - > setCursorImageUntilUnset ( " grab " ) ;
2022-06-30 12:09:05 +02:00
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
2022-07-21 19:44:34 +02:00
g_pKeybindManager - > shadowKeybinds ( ) ;
2023-07-13 18:20:40 +00:00
g_pCompositor - > focusWindow ( DRAGGINGWINDOW ) ;
2023-09-21 17:18:26 -04:00
g_pCompositor - > changeWindowZOrder ( DRAGGINGWINDOW , true ) ;
2022-06-30 12:09:05 +02:00
}
void IHyprLayout : : onEndDragWindow ( ) {
2024-04-27 12:43:12 +01:00
const auto DRAGGINGWINDOW = g_pInputManager - > currentlyDraggedWindow . lock ( ) ;
2022-06-30 12:09:05 +02:00
2024-03-06 03:15:44 +03:00
m_iMouseMoveEventCount = 1 ;
2024-04-27 12:43:12 +01:00
if ( ! validMapped ( DRAGGINGWINDOW ) ) {
2023-02-18 23:35:31 +01:00
if ( DRAGGINGWINDOW ) {
g_pInputManager - > unsetCursorImage ( ) ;
2024-04-27 12:43:12 +01:00
g_pInputManager - > currentlyDraggedWindow . reset ( ) ;
2023-02-18 23:35:31 +01:00
}
2022-06-30 12:09:05 +02:00
return ;
2023-02-18 23:35:31 +01:00
}
g_pInputManager - > unsetCursorImage ( ) ;
2024-04-27 12:43:12 +01:00
g_pInputManager - > currentlyDraggedWindow . reset ( ) ;
g_pInputManager - > m_bWasDraggingWindow = true ;
2023-01-02 12:06:06 +01:00
2024-10-08 12:20:41 +02:00
if ( g_pInputManager - > dragMode = = MBIND_MOVE ) {
2023-11-19 12:29:01 +00:00
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
const auto MOUSECOORDS = g_pInputManager - > getMouseCoordsInternal ( ) ;
2024-10-08 12:20:41 +02:00
PHLWINDOW pWindow = g_pCompositor - > vectorToWindowUnified ( MOUSECOORDS , RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING , DRAGGINGWINDOW ) ;
2023-11-19 12:29:01 +00:00
2024-02-04 15:40:20 +00:00
if ( pWindow ) {
2023-12-28 22:54:41 +00:00
if ( pWindow - > checkInputOnDecos ( INPUT_TYPE_DRAG_END , MOUSECOORDS , DRAGGINGWINDOW ) )
return ;
2023-11-19 12:29:01 +00:00
2024-10-27 00:44:55 +00:00
const bool FLOATEDINTOTILED = ! pWindow - > m_bIsFloating & & ! DRAGGINGWINDOW - > m_bDraggingTiled ;
static auto PDRAGINTOGROUP = CConfigValue < Hyprlang : : INT > ( " group:drag_into_group " ) ;
2024-10-30 10:00:58 +00:00
2024-10-27 00:44:55 +00:00
if ( pWindow - > m_sGroupData . pNextWindow . lock ( ) & & DRAGGINGWINDOW - > canBeGroupedInto ( pWindow ) & & * PDRAGINTOGROUP = = 1 & & ! FLOATEDINTOTILED ) {
2024-10-30 10:00:58 +00:00
2024-10-22 23:51:25 +00:00
if ( DRAGGINGWINDOW - > m_sGroupData . pNextWindow ) {
2024-10-30 10:00:58 +00:00
PHLWINDOW next = DRAGGINGWINDOW - > m_sGroupData . pNextWindow . lock ( ) ;
while ( next ! = DRAGGINGWINDOW ) {
next - > m_bIsFloating = pWindow - > m_bIsFloating ; // match the floating state of group members
next - > m_vRealSize = pWindow - > m_vRealSize . goal ( ) ; // match the size of group members
next - > m_vRealPosition = pWindow - > m_vRealPosition . goal ( ) ; // match the position of group members
next = next - > m_sGroupData . pNextWindow . lock ( ) ;
2024-10-08 12:20:41 +02:00
}
}
2024-11-06 17:52:10 +01:00
DRAGGINGWINDOW - > m_bIsFloating = pWindow - > m_bIsFloating ; // match the floating state of the window
DRAGGINGWINDOW - > m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize ;
DRAGGINGWINDOW - > m_bDraggingTiled = false ;
2024-10-08 12:20:41 +02:00
if ( pWindow - > m_bIsFloating )
g_pXWaylandManager - > setWindowSize ( DRAGGINGWINDOW , pWindow - > m_vRealSize . goal ( ) ) ; // match the size of the window
2024-03-03 18:39:20 +00:00
static auto USECURRPOS = CConfigValue < Hyprlang : : INT > ( " group:insert_after_current " ) ;
( * USECURRPOS ? pWindow : pWindow - > getGroupTail ( ) ) - > insertWindowToGroup ( DRAGGINGWINDOW ) ;
2023-11-19 12:29:01 +00:00
pWindow - > setGroupCurrent ( DRAGGINGWINDOW ) ;
2024-12-21 16:35:47 +00:00
DRAGGINGWINDOW - > applyGroupRules ( ) ;
2023-11-19 12:29:01 +00:00
DRAGGINGWINDOW - > updateWindowDecos ( ) ;
if ( ! DRAGGINGWINDOW - > getDecorationByType ( DECORATION_GROUPBAR ) )
DRAGGINGWINDOW - > addWindowDeco ( std : : make_unique < CHyprGroupBarDecoration > ( DRAGGINGWINDOW ) ) ;
}
}
2022-06-30 12:09:05 +02:00
}
2024-10-08 12:20:41 +02:00
if ( DRAGGINGWINDOW - > m_bDraggingTiled ) {
DRAGGINGWINDOW - > m_bIsFloating = false ;
g_pInputManager - > refocus ( ) ;
changeWindowFloatingMode ( DRAGGINGWINDOW ) ;
DRAGGINGWINDOW - > m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize ;
}
2022-06-30 12:09:05 +02:00
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
2023-08-05 18:53:13 +00:00
g_pCompositor - > focusWindow ( DRAGGINGWINDOW ) ;
2023-10-29 20:14:47 +00:00
g_pInputManager - > m_bWasDraggingWindow = false ;
2022-06-30 12:09:05 +02:00
}
2024-10-31 07:21:08 -04:00
static inline bool canSnap ( const double SIDEA , const double SIDEB , const double GAP ) {
return std : : abs ( SIDEA - SIDEB ) < GAP ;
2024-10-21 11:08:25 -04:00
}
2024-10-31 07:21:08 -04:00
static void snapMove ( double & start , double & end , const double P ) {
end = P + ( end - start ) ;
start = P ;
2024-10-21 11:08:25 -04:00
}
2024-10-31 07:21:08 -04:00
static void snapResize ( double & start , double & end , const double P ) {
start = P ;
2024-10-21 11:08:25 -04:00
}
typedef std : : function < void ( double & , double & , const double ) > SnapFn ;
2024-10-31 07:21:08 -04:00
static void performSnap ( Vector2D & sourcePos , Vector2D & sourceSize , PHLWINDOW DRAGGINGWINDOW , const eMouseBindMode MODE , const int CORNER , const Vector2D & BEGINSIZE ) {
static auto SNAPWINDOWGAP = CConfigValue < Hyprlang : : INT > ( " general:snap:window_gap " ) ;
static auto SNAPMONITORGAP = CConfigValue < Hyprlang : : INT > ( " general:snap:monitor_gap " ) ;
static auto SNAPBORDEROVERLAP = CConfigValue < Hyprlang : : INT > ( " general:snap:border_overlap " ) ;
2024-10-21 11:08:25 -04:00
2024-10-31 07:21:08 -04:00
const SnapFn SNAP = ( MODE = = MBIND_MOVE ) ? snapMove : snapResize ;
int snaps = 0 ;
2024-10-21 11:08:25 -04:00
2024-10-31 07:21:08 -04:00
const bool OVERLAP = * SNAPBORDEROVERLAP ;
2024-10-27 23:39:52 +00:00
const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW - > getRealBorderSize ( ) ;
2024-10-31 07:21:08 -04:00
struct SRange {
double start = 0 ;
double end = 0 ;
} ;
SRange sourceX = { sourcePos . x , sourcePos . x + sourceSize . x } ;
SRange sourceY = { sourcePos . y , sourcePos . y + sourceSize . y } ;
2024-10-27 23:39:52 +00:00
2024-10-21 11:08:25 -04:00
if ( * SNAPWINDOWGAP ) {
2025-01-06 11:37:13 -05:00
const double GAPSIZE = * SNAPWINDOWGAP ;
const auto WSID = DRAGGINGWINDOW - > workspaceID ( ) ;
const bool HASFULLSCREEN = DRAGGINGWINDOW - > m_pWorkspace & & DRAGGINGWINDOW - > m_pWorkspace - > m_bHasFullscreenWindow ;
2024-10-21 11:08:25 -04:00
for ( auto & other : g_pCompositor - > m_vWindows ) {
2025-01-06 11:37:13 -05:00
if ( ( HASFULLSCREEN & & ! other - > m_bCreatedOverFullscreen ) | | other = = DRAGGINGWINDOW | | other - > workspaceID ( ) ! = WSID | | ! other - > m_bIsMapped | | other - > m_bFadingOut | |
other - > isX11OverrideRedirect ( ) )
2024-10-21 11:08:25 -04:00
continue ;
2024-10-31 07:21:08 -04:00
const int OTHERBORDERSIZE = other - > getRealBorderSize ( ) ;
const double BORDERSIZE = OVERLAP ? std : : max ( DRAGGINGBORDERSIZE , OTHERBORDERSIZE ) : ( DRAGGINGBORDERSIZE + OTHERBORDERSIZE ) ;
2024-10-21 11:08:25 -04:00
2024-10-31 07:21:08 -04:00
const CBox SURF = other - > getWindowMainSurfaceBox ( ) ;
const SRange SURFBX = { SURF . x - BORDERSIZE , SURF . x + SURF . w + BORDERSIZE } ;
const SRange SURFBY = { SURF . y - BORDERSIZE , SURF . y + SURF . h + BORDERSIZE } ;
2024-10-21 11:08:25 -04:00
2024-10-31 07:21:08 -04:00
// only snap windows if their ranges overlap in the opposite axis
if ( sourceY . start < = SURFBY . end & & SURFBY . start < = sourceY . end ) {
if ( CORNER & ( CORNER_TOPLEFT | CORNER_BOTTOMLEFT ) & & canSnap ( sourceX . start , SURFBX . end , GAPSIZE ) ) {
SNAP ( sourceX . start , sourceX . end , SURFBX . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_LEFT ;
2024-10-31 07:21:08 -04:00
} else if ( CORNER & ( CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT ) & & canSnap ( sourceX . end , SURFBX . start , GAPSIZE ) ) {
SNAP ( sourceX . end , sourceX . start , SURFBX . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_RIGHT ;
}
}
2024-10-31 07:21:08 -04:00
if ( sourceX . start < = SURFBX . end & & SURFBX . start < = sourceX . end ) {
if ( CORNER & ( CORNER_TOPLEFT | CORNER_TOPRIGHT ) & & canSnap ( sourceY . start , SURFBY . end , GAPSIZE ) ) {
SNAP ( sourceY . start , sourceY . end , SURFBY . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_UP ;
2024-10-31 07:21:08 -04:00
} else if ( CORNER & ( CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT ) & & canSnap ( sourceY . end , SURFBY . start , GAPSIZE ) ) {
SNAP ( sourceY . end , sourceY . start , SURFBY . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_DOWN ;
}
}
// corner snapping
2024-10-31 07:21:08 -04:00
const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE ;
2024-12-27 16:49:45 -05:00
if ( sourceX . start = = SURFBX . end | | SURFBX . start = = sourceX . end ) {
2024-10-31 07:21:08 -04:00
const SRange SURFY = { SURF . y - BORDERDIFF , SURF . y + SURF . h + BORDERDIFF } ;
2024-12-29 06:18:14 -05:00
if ( CORNER & ( CORNER_TOPLEFT | CORNER_TOPRIGHT ) & & ! ( snaps & SNAP_UP ) & & canSnap ( sourceY . start , SURFY . start , GAPSIZE ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceY . start , sourceY . end , SURFY . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_UP ;
2024-12-29 06:18:14 -05:00
} else if ( CORNER & ( CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT ) & & ! ( snaps & SNAP_DOWN ) & & canSnap ( sourceY . end , SURFY . end , GAPSIZE ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceY . end , sourceY . start , SURFY . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_DOWN ;
}
}
2024-12-27 16:49:45 -05:00
if ( sourceY . start = = SURFBY . end | | SURFBY . start = = sourceY . end ) {
2024-10-31 07:21:08 -04:00
const SRange SURFX = { SURF . x - BORDERDIFF , SURF . x + SURF . w + BORDERDIFF } ;
2024-12-29 06:18:14 -05:00
if ( CORNER & ( CORNER_TOPLEFT | CORNER_BOTTOMLEFT ) & & ! ( snaps & SNAP_LEFT ) & & canSnap ( sourceX . start , SURFX . start , GAPSIZE ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceX . start , sourceX . end , SURFX . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_LEFT ;
2024-12-29 06:18:14 -05:00
} else if ( CORNER & ( CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT ) & & ! ( snaps & SNAP_RIGHT ) & & canSnap ( sourceX . end , SURFX . end , GAPSIZE ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceX . end , sourceX . start , SURFX . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_RIGHT ;
}
}
}
}
if ( * SNAPMONITORGAP ) {
2024-10-31 07:21:08 -04:00
const double GAPSIZE = * SNAPMONITORGAP ;
2024-12-13 11:34:04 -05:00
const double BORDERDIFF = OVERLAP ? DRAGGINGBORDERSIZE : 0 ;
2024-10-31 07:21:08 -04:00
const auto MON = DRAGGINGWINDOW - > m_pMonitor . lock ( ) ;
2024-12-13 11:34:04 -05:00
SRange monX = { MON - > vecPosition . x + MON - > vecReservedTopLeft . x + DRAGGINGBORDERSIZE ,
MON - > vecPosition . x + MON - > vecSize . x - MON - > vecReservedBottomRight . x - DRAGGINGBORDERSIZE } ;
SRange monY = { MON - > vecPosition . y + MON - > vecReservedTopLeft . y + DRAGGINGBORDERSIZE ,
MON - > vecPosition . y + MON - > vecSize . y - MON - > vecReservedBottomRight . y - DRAGGINGBORDERSIZE } ;
2024-10-31 07:21:08 -04:00
2024-12-04 13:12:04 -05:00
if ( CORNER & ( CORNER_TOPLEFT | CORNER_BOTTOMLEFT ) & &
2024-12-13 11:34:04 -05:00
( ( MON - > vecReservedTopLeft . x > 0 & & canSnap ( sourceX . start , monX . start , GAPSIZE ) ) | |
canSnap ( sourceX . start , ( monX . start - = MON - > vecReservedTopLeft . x + BORDERDIFF ) , GAPSIZE ) ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceX . start , sourceX . end , monX . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_LEFT ;
}
2024-12-04 13:12:04 -05:00
if ( CORNER & ( CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT ) & &
2024-12-13 11:34:04 -05:00
( ( MON - > vecReservedBottomRight . x > 0 & & canSnap ( sourceX . end , monX . end , GAPSIZE ) ) | |
canSnap ( sourceX . end , ( monX . end + = MON - > vecReservedBottomRight . x + BORDERDIFF ) , GAPSIZE ) ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceX . end , sourceX . start , monX . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_RIGHT ;
}
2024-12-04 13:12:04 -05:00
if ( CORNER & ( CORNER_TOPLEFT | CORNER_TOPRIGHT ) & &
2024-12-13 11:34:04 -05:00
( ( MON - > vecReservedTopLeft . y > 0 & & canSnap ( sourceY . start , monY . start , GAPSIZE ) ) | |
canSnap ( sourceY . start , ( monY . start - = MON - > vecReservedTopLeft . y + BORDERDIFF ) , GAPSIZE ) ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceY . start , sourceY . end , monY . start ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_UP ;
}
2024-12-04 13:12:04 -05:00
if ( CORNER & ( CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT ) & &
2024-12-13 11:34:04 -05:00
( ( MON - > vecReservedBottomRight . y > 0 & & canSnap ( sourceY . end , monY . end , GAPSIZE ) ) | |
canSnap ( sourceY . end , ( monY . end + = MON - > vecReservedBottomRight . y + BORDERDIFF ) , GAPSIZE ) ) ) {
2024-10-31 07:21:08 -04:00
SNAP ( sourceY . end , sourceY . start , monY . end ) ;
2024-10-21 11:08:25 -04:00
snaps | = SNAP_DOWN ;
}
}
2024-10-31 07:21:08 -04:00
if ( MODE = = MBIND_RESIZE_FORCE_RATIO ) {
if ( ( CORNER & ( CORNER_TOPLEFT | CORNER_BOTTOMLEFT ) & & snaps & SNAP_LEFT ) | | ( CORNER & ( CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT ) & & snaps & SNAP_RIGHT ) ) {
const double SIZEY = ( sourceX . end - sourceX . start ) * ( BEGINSIZE . y / BEGINSIZE . x ) ;
if ( CORNER & ( CORNER_TOPLEFT | CORNER_TOPRIGHT ) )
sourceY . start = sourceY . end - SIZEY ;
else
sourceY . end = sourceY . start + SIZEY ;
} else if ( ( CORNER & ( CORNER_TOPLEFT | CORNER_TOPRIGHT ) & & snaps & SNAP_UP ) | | ( CORNER & ( CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT ) & & snaps & SNAP_DOWN ) ) {
const double SIZEX = ( sourceY . end - sourceY . start ) * ( BEGINSIZE . x / BEGINSIZE . y ) ;
if ( CORNER & ( CORNER_TOPLEFT | CORNER_BOTTOMLEFT ) )
sourceX . start = sourceX . end - SIZEX ;
else
sourceX . end = sourceX . start + SIZEX ;
2024-10-21 11:08:25 -04:00
}
}
2024-10-27 23:39:52 +00:00
2024-10-31 07:21:08 -04:00
sourcePos = { sourceX . start , sourceY . start } ;
sourceSize = { sourceX . end - sourceX . start , sourceY . end - sourceY . start } ;
2024-10-21 11:08:25 -04:00
}
2022-06-30 12:09:05 +02:00
void IHyprLayout : : onMouseMove ( const Vector2D & mousePos ) {
2024-07-27 16:46:19 +00:00
if ( g_pInputManager - > currentlyDraggedWindow . expired ( ) )
return ;
2024-04-27 12:43:12 +01:00
const auto DRAGGINGWINDOW = g_pInputManager - > currentlyDraggedWindow . lock ( ) ;
2022-06-30 12:09:05 +02:00
// Window invalid or drag begin size 0,0 meaning we rejected it.
2024-07-27 16:46:19 +00:00
if ( ( ! validMapped ( DRAGGINGWINDOW ) | | m_vBeginDragSizeXY = = Vector2D ( ) ) ) {
g_pKeybindManager - > changeMouseBindMode ( MBIND_INVALID ) ;
2022-06-30 12:09:05 +02:00
return ;
}
2024-03-06 03:15:44 +03:00
static auto TIMER = std : : chrono : : high_resolution_clock : : now ( ) , MSTIMER = TIMER ;
2022-12-09 17:08:04 +00:00
2024-04-02 20:32:39 +01:00
const auto SPECIAL = DRAGGINGWINDOW - > onSpecialWorkspace ( ) ;
2022-06-30 12:09:05 +02:00
2024-03-03 18:39:20 +00:00
const auto DELTA = Vector2D ( mousePos . x - m_vBeginDragXY . x , mousePos . y - m_vBeginDragXY . y ) ;
const auto TICKDELTA = Vector2D ( mousePos . x - m_vLastDragXY . x , mousePos . y - m_vLastDragXY . y ) ;
2022-08-16 21:56:54 +02:00
2024-03-03 18:39:20 +00:00
static auto PANIMATEMOUSE = CConfigValue < Hyprlang : : INT > ( " misc:animate_mouse_windowdragging " ) ;
static auto PANIMATE = CConfigValue < Hyprlang : : INT > ( " misc:animate_manual_resizes " ) ;
2023-03-04 00:14:20 +00:00
2024-10-21 11:08:25 -04:00
static auto SNAPENABLED = CConfigValue < Hyprlang : : INT > ( " general:snap:enabled " ) ;
2024-03-06 03:15:44 +03:00
const auto TIMERDELTA = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - TIMER ) . count ( ) ;
const auto MSDELTA = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - MSTIMER ) . count ( ) ;
const auto MSMONITOR = 1000.0 / g_pHyprRenderer - > m_pMostHzMonitor - > refreshRate ;
static int totalMs = 0 ;
bool canSkipUpdate = true ;
MSTIMER = std : : chrono : : high_resolution_clock : : now ( ) ;
if ( m_iMouseMoveEventCount = = 1 )
totalMs = 0 ;
if ( MSMONITOR > 16.0 ) {
totalMs + = MSDELTA < MSMONITOR ? MSDELTA : std : : round ( totalMs * 1.0 / m_iMouseMoveEventCount ) ;
m_iMouseMoveEventCount + = 1 ;
// check if time-window is enough to skip update on 60hz monitor
canSkipUpdate = std : : clamp ( MSMONITOR - TIMERDELTA , 0.0 , MSMONITOR ) > totalMs * 1.0 / m_iMouseMoveEventCount ;
}
2024-05-02 06:28:51 -07:00
if ( ( abs ( TICKDELTA . x ) < 1.f & & abs ( TICKDELTA . y ) < 1.f ) | | ( TIMERDELTA < MSMONITOR & & canSkipUpdate & & ( g_pInputManager - > dragMode ! = MBIND_MOVE | | * PANIMATEMOUSE ) ) )
2022-06-30 12:09:05 +02:00
return ;
2023-03-04 00:14:20 +00:00
TIMER = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-06-30 12:09:05 +02:00
m_vLastDragXY = mousePos ;
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
2022-09-19 19:04:48 +01:00
if ( g_pInputManager - > dragMode = = MBIND_MOVE ) {
2022-10-19 21:17:49 +01:00
2024-10-21 11:08:25 -04:00
Vector2D newPos = m_vBeginDragPositionXY + DELTA ;
Vector2D newSize = DRAGGINGWINDOW - > m_vRealSize . goal ( ) ;
if ( * SNAPENABLED & & ! DRAGGINGWINDOW - > m_bDraggingTiled )
performSnap ( newPos , newSize , DRAGGINGWINDOW , MBIND_MOVE , - 1 , m_vBeginDragSizeXY ) ;
CBox wb = { newPos , newSize } ;
2023-11-07 20:47:09 +00:00
wb . round ( ) ;
2024-03-03 18:39:20 +00:00
if ( * PANIMATEMOUSE )
2023-11-07 20:47:09 +00:00
DRAGGINGWINDOW - > m_vRealPosition = wb . pos ( ) ;
else
DRAGGINGWINDOW - > m_vRealPosition . setValueAndWarp ( wb . pos ( ) ) ;
2022-06-30 12:09:05 +02:00
2024-03-02 01:35:17 +01:00
g_pXWaylandManager - > setWindowSize ( DRAGGINGWINDOW , DRAGGINGWINDOW - > m_vRealSize . goal ( ) ) ;
2023-08-08 16:52:20 +00:00
} else if ( g_pInputManager - > dragMode = = MBIND_RESIZE | | g_pInputManager - > dragMode = = MBIND_RESIZE_FORCE_RATIO | | g_pInputManager - > dragMode = = MBIND_RESIZE_BLOCK_RATIO ) {
2022-06-30 12:09:05 +02:00
if ( DRAGGINGWINDOW - > m_bIsFloating ) {
2022-08-05 17:58:08 +02:00
2024-11-17 19:31:54 +00:00
Vector2D MINSIZE = DRAGGINGWINDOW - > requestedMinSize ( ) . clamp ( DRAGGINGWINDOW - > m_sWindowData . minSize . valueOr ( Vector2D ( 20 , 20 ) ) ) ;
2024-07-11 14:10:42 +00:00
Vector2D MAXSIZE ;
if ( DRAGGINGWINDOW - > m_sWindowData . maxSize . hasValue ( ) )
2024-11-17 19:31:54 +00:00
MAXSIZE = DRAGGINGWINDOW - > requestedMaxSize ( ) . clamp ( { } , DRAGGINGWINDOW - > m_sWindowData . maxSize . value ( ) ) ;
2024-07-11 14:10:42 +00:00
else
2024-11-17 19:31:54 +00:00
MAXSIZE = DRAGGINGWINDOW - > requestedMaxSize ( ) . clamp ( { } , Vector2D ( std : : numeric_limits < double > : : max ( ) , std : : numeric_limits < double > : : max ( ) ) ) ;
2022-10-03 22:41:05 +01:00
Vector2D newSize = m_vBeginDragSizeXY ;
2022-12-16 17:17:31 +00:00
Vector2D newPos = m_vBeginDragPositionXY ;
2022-10-03 22:41:05 +01:00
2023-08-08 16:52:20 +00:00
if ( m_eGrabbedCorner = = CORNER_BOTTOMRIGHT )
newSize = newSize + DELTA ;
else if ( m_eGrabbedCorner = = CORNER_TOPLEFT )
newSize = newSize - DELTA ;
else if ( m_eGrabbedCorner = = CORNER_TOPRIGHT )
newSize = newSize + Vector2D ( DELTA . x , - DELTA . y ) ;
else if ( m_eGrabbedCorner = = CORNER_BOTTOMLEFT )
newSize = newSize + Vector2D ( - DELTA . x , DELTA . y ) ;
2024-10-21 11:08:25 -04:00
eMouseBindMode mode = g_pInputManager - > dragMode ;
if ( DRAGGINGWINDOW - > m_sWindowData . keepAspectRatio . valueOrDefault ( ) & & mode ! = MBIND_RESIZE_BLOCK_RATIO )
mode = MBIND_RESIZE_FORCE_RATIO ;
if ( m_vBeginDragSizeXY . x > = 1 & & m_vBeginDragSizeXY . y > = 1 & & mode = = MBIND_RESIZE_FORCE_RATIO ) {
2023-08-08 16:52:20 +00:00
const float RATIO = m_vBeginDragSizeXY . y / m_vBeginDragSizeXY . x ;
if ( MINSIZE . x * RATIO > MINSIZE . y )
MINSIZE = Vector2D ( MINSIZE . x , MINSIZE . x * RATIO ) ;
else
MINSIZE = Vector2D ( MINSIZE . y / RATIO , MINSIZE . y ) ;
if ( MAXSIZE . x * RATIO < MAXSIZE . y )
MAXSIZE = Vector2D ( MAXSIZE . x , MAXSIZE . x * RATIO ) ;
else
MAXSIZE = Vector2D ( MAXSIZE . y / RATIO , MAXSIZE . y ) ;
if ( newSize . x * RATIO > newSize . y )
newSize = Vector2D ( newSize . x , newSize . x * RATIO ) ;
else
newSize = Vector2D ( newSize . y / RATIO , newSize . y ) ;
2022-10-03 22:41:05 +01:00
}
2023-08-08 16:52:20 +00:00
newSize = newSize . clamp ( MINSIZE , MAXSIZE ) ;
if ( m_eGrabbedCorner = = CORNER_TOPLEFT )
newPos = newPos - newSize + m_vBeginDragSizeXY ;
else if ( m_eGrabbedCorner = = CORNER_TOPRIGHT )
2024-06-19 16:20:06 +02:00
newPos = newPos + Vector2D ( 0.0 , ( m_vBeginDragSizeXY - newSize ) . y ) ;
2023-08-08 16:52:20 +00:00
else if ( m_eGrabbedCorner = = CORNER_BOTTOMLEFT )
2024-06-19 16:20:06 +02:00
newPos = newPos + Vector2D ( ( m_vBeginDragSizeXY - newSize ) . x , 0.0 ) ;
2023-08-08 16:52:20 +00:00
2024-10-21 11:08:25 -04:00
if ( * SNAPENABLED ) {
performSnap ( newPos , newSize , DRAGGINGWINDOW , mode , m_eGrabbedCorner , m_vBeginDragSizeXY ) ;
newSize = newSize . clamp ( MINSIZE , MAXSIZE ) ;
}
2023-11-06 17:00:37 +00:00
CBox wb = { newPos , newSize } ;
wb . round ( ) ;
2024-03-03 18:39:20 +00:00
if ( * PANIMATE ) {
2023-11-06 17:00:37 +00:00
DRAGGINGWINDOW - > m_vRealSize = wb . size ( ) ;
DRAGGINGWINDOW - > m_vRealPosition = wb . pos ( ) ;
2022-08-16 21:56:54 +02:00
} else {
2023-11-06 17:00:37 +00:00
DRAGGINGWINDOW - > m_vRealSize . setValueAndWarp ( wb . size ( ) ) ;
DRAGGINGWINDOW - > m_vRealPosition . setValueAndWarp ( wb . pos ( ) ) ;
2022-08-16 21:56:54 +02:00
}
2022-09-25 20:07:48 +02:00
2024-03-02 01:35:17 +01:00
g_pXWaylandManager - > setWindowSize ( DRAGGINGWINDOW , DRAGGINGWINDOW - > m_vRealSize . goal ( ) ) ;
2022-06-30 12:09:05 +02:00
} else {
2023-07-13 16:52:11 +02:00
resizeActiveWindow ( TICKDELTA , m_eGrabbedCorner , DRAGGINGWINDOW ) ;
2022-06-30 12:09:05 +02:00
}
}
// get middle point
2024-03-02 01:35:17 +01:00
Vector2D middle = DRAGGINGWINDOW - > m_vRealPosition . value ( ) + DRAGGINGWINDOW - > m_vRealSize . value ( ) / 2.f ;
2022-06-30 12:09:05 +02:00
// and check its monitor
const auto PMONITOR = g_pCompositor - > getMonitorFromVector ( middle ) ;
2022-12-09 17:08:04 +00:00
if ( PMONITOR & & ! SPECIAL ) {
2024-10-27 18:45:38 +00:00
DRAGGINGWINDOW - > m_pMonitor = PMONITOR ;
2022-08-21 18:01:26 +03:00
DRAGGINGWINDOW - > moveToWorkspace ( PMONITOR - > activeWorkspace ) ;
2023-03-18 16:30:29 +00:00
DRAGGINGWINDOW - > updateGroupOutputs ( ) ;
2022-09-25 20:07:48 +02:00
2022-08-06 20:57:38 +02:00
DRAGGINGWINDOW - > updateToplevel ( ) ;
2022-06-30 12:09:05 +02:00
}
2022-08-05 19:23:53 +02:00
DRAGGINGWINDOW - > updateWindowDecos ( ) ;
2022-06-30 12:09:05 +02:00
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : changeWindowFloatingMode ( PHLWINDOW pWindow ) {
2022-06-30 12:09:05 +02:00
2024-07-31 17:55:52 +00:00
if ( pWindow - > isFullscreen ( ) ) {
2023-08-28 22:55:52 +02:00
Debug : : log ( LOG , " changeWindowFloatingMode: fullscreen " ) ;
2024-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( pWindow , FSMODE_NONE ) ;
2022-06-30 12:09:05 +02:00
}
2022-09-10 13:11:02 +02:00
pWindow - > m_bPinned = false ;
2022-06-30 12:09:05 +02:00
const auto TILED = isWindowTiled ( pWindow ) ;
2022-12-09 18:51:44 +00:00
// event
2024-04-27 12:43:12 +01:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " changefloatingmode " , std : : format ( " {:x},{} " , ( uintptr_t ) pWindow . get ( ) , ( int ) TILED ) } ) ;
2023-02-19 20:54:53 +00:00
EMIT_HOOK_EVENT ( " changeFloatingMode " , pWindow ) ;
2022-12-09 18:51:44 +00:00
2022-06-30 12:09:05 +02:00
if ( ! TILED ) {
2024-10-27 18:45:38 +00:00
const auto PNEWMON = g_pCompositor - > getMonitorFromVector ( pWindow - > m_vRealPosition . value ( ) + pWindow - > m_vRealSize . value ( ) / 2.f ) ;
pWindow - > m_pMonitor = PNEWMON ;
2024-04-02 20:32:39 +01:00
pWindow - > moveToWorkspace ( PNEWMON - > activeSpecialWorkspace ? PNEWMON - > activeSpecialWorkspace : PNEWMON - > activeWorkspace ) ;
2023-03-18 16:30:29 +00:00
pWindow - > updateGroupOutputs ( ) ;
2022-06-30 12:09:05 +02:00
2024-04-02 20:32:39 +01:00
const auto PWORKSPACE = PNEWMON - > activeSpecialWorkspace ? PNEWMON - > activeSpecialWorkspace : PNEWMON - > activeWorkspace ;
2024-03-10 22:31:49 +00:00
if ( PWORKSPACE - > m_bHasFullscreenWindow )
2024-11-22 16:01:02 +00:00
g_pCompositor - > setWindowFullscreenInternal ( PWORKSPACE - > getFullscreenWindow ( ) , FSMODE_NONE ) ;
2024-03-10 22:31:49 +00:00
2022-06-30 12:09:05 +02:00
// save real pos cuz the func applies the default 5,5 mid
2024-03-02 01:35:17 +01:00
const auto PSAVEDPOS = pWindow - > m_vRealPosition . goal ( ) ;
const auto PSAVEDSIZE = pWindow - > m_vRealSize . goal ( ) ;
2022-06-30 12:09:05 +02:00
// if the window is pseudo, update its size
2023-11-18 20:59:12 +01:00
if ( ! pWindow - > m_bDraggingTiled )
2024-03-02 01:35:17 +01:00
pWindow - > m_vPseudoSize = pWindow - > m_vRealSize . goal ( ) ;
2022-06-30 12:09:05 +02:00
2022-08-05 17:52:14 +02:00
pWindow - > m_vLastFloatingSize = PSAVEDSIZE ;
2024-10-08 12:20:41 +02:00
// move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back.
2022-10-19 21:32:30 +01:00
pWindow - > m_vPosition = Vector2D ( - 999999 , - 999999 ) ;
2024-10-08 12:20:41 +02:00
onWindowCreatedTiling ( pWindow ) ;
2022-06-30 12:09:05 +02:00
pWindow - > m_vRealPosition . setValue ( PSAVEDPOS ) ;
pWindow - > m_vRealSize . setValue ( PSAVEDSIZE ) ;
// fix pseudo leaving artifacts
2024-10-27 18:45:38 +00:00
g_pHyprRenderer - > damageMonitor ( pWindow - > m_pMonitor . lock ( ) ) ;
2022-10-24 12:25:36 +01:00
2024-05-05 17:16:00 +01:00
if ( pWindow = = g_pCompositor - > m_pLastWindow )
2022-10-24 12:25:36 +01:00
m_pLastTiledWindow = pWindow ;
2022-06-30 12:09:05 +02:00
} else {
onWindowRemovedTiling ( pWindow ) ;
2023-09-21 17:18:26 -04:00
g_pCompositor - > changeWindowZOrder ( pWindow , true ) ;
2022-07-08 21:52:52 +02:00
2024-03-02 01:35:17 +01:00
CBox wb = { pWindow - > m_vRealPosition . goal ( ) + ( pWindow - > m_vRealSize . goal ( ) - pWindow - > m_vLastFloatingSize ) / 2.f , pWindow - > m_vLastFloatingSize } ;
2024-01-10 18:08:58 +01:00
wb . round ( ) ;
2024-05-18 18:28:48 +00:00
if ( ! ( pWindow - > m_bIsFloating & & pWindow - > m_bIsPseudotiled ) & & DELTALESSTHAN ( pWindow - > m_vRealSize . value ( ) . x , pWindow - > m_vLastFloatingSize . x , 10 ) & &
2024-03-02 01:35:17 +01:00
DELTALESSTHAN ( pWindow - > m_vRealSize . value ( ) . y , pWindow - > m_vLastFloatingSize . y , 10 ) ) {
2024-01-10 18:08:58 +01:00
wb = { wb . pos ( ) + Vector2D { 10 , 10 } , wb . size ( ) - Vector2D { 20 , 20 } } ;
2023-04-06 19:45:59 +01:00
}
2024-01-10 18:08:58 +01:00
pWindow - > m_vRealPosition = wb . pos ( ) ;
pWindow - > m_vRealSize = wb . size ( ) ;
2022-07-08 21:52:52 +02:00
2024-01-10 18:08:58 +01:00
pWindow - > m_vSize = wb . pos ( ) ;
pWindow - > m_vPosition = wb . size ( ) ;
2022-11-09 22:01:53 +00:00
2024-10-27 18:45:38 +00:00
g_pHyprRenderer - > damageMonitor ( pWindow - > m_pMonitor . lock ( ) ) ;
2022-08-05 18:08:23 +02:00
2024-07-11 14:10:42 +00:00
pWindow - > unsetWindowData ( PRIORITY_LAYOUT ) ;
2024-07-15 09:57:52 +00:00
pWindow - > updateWindowData ( ) ;
2022-10-24 12:25:36 +01:00
2024-05-05 17:16:00 +01:00
if ( pWindow = = m_pLastTiledWindow )
2024-04-27 12:43:12 +01:00
m_pLastTiledWindow . reset ( ) ;
2022-06-30 12:09:05 +02:00
}
2022-08-06 20:57:38 +02:00
2022-08-11 19:29:39 +02:00
g_pCompositor - > updateWindowAnimatedDecorationValues ( pWindow ) ;
2022-08-06 20:57:38 +02:00
pWindow - > updateToplevel ( ) ;
2022-06-30 12:09:05 +02:00
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : moveActiveWindow ( const Vector2D & delta , PHLWINDOW pWindow ) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor - > m_pLastWindow . lock ( ) ;
2022-06-30 12:09:05 +02:00
2024-04-27 12:43:12 +01:00
if ( ! validMapped ( PWINDOW ) )
2022-06-30 12:09:05 +02:00
return ;
if ( ! PWINDOW - > m_bIsFloating ) {
Debug : : log ( LOG , " Dwindle cannot move a tiled window in moveActiveWindow! " ) ;
return ;
}
2024-03-18 19:52:52 -07:00
PWINDOW - > setAnimationsToMove ( ) ;
2024-03-02 01:35:17 +01:00
PWINDOW - > m_vRealPosition = PWINDOW - > m_vRealPosition . goal ( ) + delta ;
2022-06-30 12:09:05 +02:00
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2022-09-25 20:07:48 +02:00
}
2022-10-24 12:25:36 +01:00
2024-04-27 12:43:12 +01:00
void IHyprLayout : : onWindowFocusChange ( PHLWINDOW pNewFocus ) {
2022-10-24 12:25:36 +01:00
m_pLastTiledWindow = pNewFocus & & ! pNewFocus - > m_bIsFloating ? pNewFocus : m_pLastTiledWindow ;
}
2024-04-27 12:43:12 +01:00
PHLWINDOW IHyprLayout : : getNextWindowCandidate ( PHLWINDOW pWindow ) {
2022-10-24 12:25:36 +01:00
// although we don't expect nullptrs here, let's verify jic
if ( ! pWindow )
return nullptr ;
2024-04-02 20:32:39 +01:00
const auto PWORKSPACE = pWindow - > m_pWorkspace ;
2022-10-24 12:25:36 +01:00
// first of all, if this is a fullscreen workspace,
if ( PWORKSPACE - > m_bHasFullscreenWindow )
2024-11-22 16:01:02 +00:00
return PWORKSPACE - > getFullscreenWindow ( ) ;
2022-10-24 12:25:36 +01:00
if ( pWindow - > m_bIsFloating ) {
2022-11-27 12:11:45 +00:00
// find whether there is a floating window below this one
2024-08-26 20:24:30 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-08-30 14:12:23 +02:00
if ( w - > m_bIsMapped & & ! w - > isHidden ( ) & & w - > m_bIsFloating & & ! w - > isX11OverrideRedirect ( ) & & w - > m_pWorkspace = = pWindow - > m_pWorkspace & & ! w - > m_bX11ShouldntFocus & &
2024-07-11 14:10:42 +00:00
! w - > m_sWindowData . noFocus . valueOrDefault ( ) & & w ! = pWindow ) {
2022-12-16 17:17:31 +00:00
if ( VECINRECT ( ( pWindow - > m_vSize / 2.f + pWindow - > m_vPosition ) , w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vPosition . x + w - > m_vSize . x ,
w - > m_vPosition . y + w - > m_vSize . y ) ) {
2024-04-27 12:43:12 +01:00
return w ;
2022-11-27 12:11:45 +00:00
}
}
}
// let's try the last tiled window.
2024-05-05 17:16:00 +01:00
if ( m_pLastTiledWindow . lock ( ) & & m_pLastTiledWindow - > m_pWorkspace = = pWindow - > m_pWorkspace )
2024-04-27 12:43:12 +01:00
return m_pLastTiledWindow . lock ( ) ;
2022-10-24 12:25:36 +01:00
// if we don't, let's try to find any window that is in the middle
2024-02-04 15:40:20 +00:00
if ( const auto PWINDOWCANDIDATE = g_pCompositor - > vectorToWindowUnified ( pWindow - > middle ( ) , RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING ) ;
PWINDOWCANDIDATE & & PWINDOWCANDIDATE ! = pWindow )
2022-10-24 12:25:36 +01:00
return PWINDOWCANDIDATE ;
// if not, floating window
2024-08-26 20:24:30 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-08-30 14:12:23 +02:00
if ( w - > m_bIsMapped & & ! w - > isHidden ( ) & & w - > m_bIsFloating & & ! w - > isX11OverrideRedirect ( ) & & w - > m_pWorkspace = = pWindow - > m_pWorkspace & & ! w - > m_bX11ShouldntFocus & &
2024-07-11 14:10:42 +00:00
! w - > m_sWindowData . noFocus . valueOrDefault ( ) & & w ! = pWindow )
2024-04-27 12:43:12 +01:00
return w ;
2022-10-24 12:25:36 +01:00
}
// if there is no candidate, too bad
return nullptr ;
}
// if it was a tiled window, we first try to find the window that will replace it.
2024-02-04 15:40:20 +00:00
auto pWindowCandidate = g_pCompositor - > vectorToWindowUnified ( pWindow - > middle ( ) , RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING ) ;
2022-10-24 12:25:36 +01:00
2023-12-12 16:44:31 +00:00
if ( ! pWindowCandidate )
2024-11-22 16:01:02 +00:00
pWindowCandidate = PWORKSPACE - > getTopLeftWindow ( ) ;
2023-12-12 16:44:31 +00:00
if ( ! pWindowCandidate )
2024-11-22 16:01:02 +00:00
pWindowCandidate = PWORKSPACE - > getFirstWindow ( ) ;
2023-12-12 16:44:31 +00:00
if ( ! pWindowCandidate | | pWindow = = pWindowCandidate | | ! pWindowCandidate - > m_bIsMapped | | pWindowCandidate - > isHidden ( ) | | pWindowCandidate - > m_bX11ShouldntFocus | |
2024-10-27 18:45:38 +00:00
pWindowCandidate - > isX11OverrideRedirect ( ) | | pWindowCandidate - > m_pMonitor ! = g_pCompositor - > m_pLastMonitor )
2022-10-24 12:25:36 +01:00
return nullptr ;
2023-12-12 16:44:31 +00:00
return pWindowCandidate ;
2022-10-24 12:25:36 +01:00
}
2022-11-29 03:04:24 +08:00
2024-04-27 12:43:12 +01:00
bool IHyprLayout : : isWindowReachable ( PHLWINDOW pWindow ) {
2024-05-05 17:16:00 +01:00
return pWindow & & ( ! pWindow - > isHidden ( ) | | pWindow - > m_sGroupData . pNextWindow ) ;
2023-09-12 14:37:08 -07:00
}
2024-04-27 12:43:12 +01:00
void IHyprLayout : : bringWindowToTop ( PHLWINDOW pWindow ) {
2023-09-12 14:37:08 -07:00
if ( pWindow = = nullptr )
return ;
2024-05-05 17:16:00 +01:00
if ( pWindow - > isHidden ( ) & & pWindow - > m_sGroupData . pNextWindow ) {
2023-07-19 03:39:45 -07:00
// grouped, change the current to this window
pWindow - > setGroupCurrent ( pWindow ) ;
}
2023-09-12 14:37:08 -07:00
}
2023-07-19 03:39:45 -07:00
2024-04-27 12:43:12 +01:00
void IHyprLayout : : requestFocusForWindow ( PHLWINDOW pWindow ) {
2023-09-12 14:37:08 -07:00
bringWindowToTop ( pWindow ) ;
2023-07-19 03:39:45 -07:00
g_pCompositor - > focusWindow ( pWindow ) ;
2024-03-06 01:56:06 +08:00
g_pCompositor - > warpCursorTo ( pWindow - > middle ( ) ) ;
2023-07-19 03:39:45 -07:00
}
2024-04-27 12:43:12 +01:00
Vector2D IHyprLayout : : predictSizeForNewWindowFloating ( PHLWINDOW pWindow ) { // get all rules, see if we have any size overrides.
2024-03-29 00:43:50 +00:00
Vector2D sizeOverride = { } ;
if ( g_pCompositor - > m_pLastMonitor ) {
2024-08-26 20:24:30 +02:00
for ( auto const & r : g_pConfigManager - > getMatchingRules ( pWindow , true , true ) ) {
2024-12-16 19:05:24 +01:00
if ( r - > ruleType ! = CWindowRule : : RULE_SIZE )
continue ;
2024-10-30 18:58:36 +00:00
2024-12-16 19:05:24 +01:00
try {
const auto VALUE = r - > szRule . substr ( r - > szRule . find ( ' ' ) + 1 ) ;
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
2024-12-16 19:05:24 +01:00
const float SIZEX = SIZEXSTR = = " max " ? std : : clamp ( MAXSIZE . x , MIN_WINDOW_SIZE , g_pCompositor - > m_pLastMonitor - > vecSize . x ) :
stringToPercentage ( SIZEXSTR , g_pCompositor - > m_pLastMonitor - > vecSize . x ) ;
2024-03-29 00:43:50 +00:00
2024-12-16 19:05:24 +01:00
const float SIZEY = SIZEYSTR = = " max " ? std : : clamp ( MAXSIZE . y , MIN_WINDOW_SIZE , g_pCompositor - > m_pLastMonitor - > vecSize . y ) :
stringToPercentage ( SIZEYSTR , g_pCompositor - > m_pLastMonitor - > vecSize . y ) ;
2024-03-29 00:43:50 +00:00
2024-12-16 19:05:24 +01:00
sizeOverride = { SIZEX , SIZEY } ;
} catch ( . . . ) { Debug : : log ( LOG , " Rule size failed, rule: {} -> {} " , r - > szRule , r - > szValue ) ; }
break ;
2024-03-29 00:43:50 +00:00
}
}
return sizeOverride ;
}
2024-04-27 12:43:12 +01:00
Vector2D IHyprLayout : : predictSizeForNewWindow ( PHLWINDOW pWindow ) {
2024-03-29 00:43:50 +00:00
bool shouldBeFloated = g_pXWaylandManager - > shouldBeFloated ( pWindow , true ) ;
if ( ! shouldBeFloated ) {
2024-08-26 17:25:39 +02:00
for ( auto const & r : g_pConfigManager - > getMatchingRules ( pWindow , true , true ) ) {
2024-12-16 19:05:24 +01:00
if ( r - > ruleType ! = CWindowRule : : RULE_FLOAT )
continue ;
shouldBeFloated = true ;
break ;
2024-03-29 00:43:50 +00:00
}
}
Vector2D sizePredicted = { } ;
if ( ! shouldBeFloated )
sizePredicted = predictSizeForNewWindowTiled ( ) ;
else
sizePredicted = predictSizeForNewWindowFloating ( pWindow ) ;
2024-05-10 23:28:33 +01:00
Vector2D maxSize = pWindow - > m_pXDGSurface - > toplevel - > pending . maxSize ;
2024-03-29 00:43:50 +00:00
if ( ( maxSize . x > 0 & & maxSize . x < sizePredicted . x ) | | ( maxSize . y > 0 & & maxSize . y < sizePredicted . y ) )
sizePredicted = { } ;
return sizePredicted ;
2024-02-28 11:45:43 +00:00
}
2024-12-07 18:51:18 +01:00
IHyprLayout : : ~ IHyprLayout ( ) = default ;