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 ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
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 ) ;
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 ) {
2022-06-30 12:09:05 +02:00
return ; // no-op
}
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 ) ;
2023-08-15 20:09:32 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
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 ) {
static auto AUTOGROUP = CConfigValue < Hyprlang : : INT > ( " group:auto_group " ) ;
if ( ( * AUTOGROUP | | g_pInputManager - > m_bWasDraggingWindow ) // check if auto_group is enabled, or, if the user is manually dragging the window into the group.
& & g_pCompositor - > m_pLastWindow . lock ( ) // check if a focused window exists.
& & g_pCompositor - > m_pLastWindow ! = pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group.
& & g_pCompositor - > m_pLastWindow - > m_pWorkspace = =
pWindow
- > m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it.
& & g_pCompositor - > m_pLastWindow - > m_sGroupData . pNextWindow . lock ( ) // check if the focused window is a group
& & pWindow - > canBeGroupedInto ( g_pCompositor - > m_pLastWindow . lock ( ) ) // check if the new window can be grouped into the focused group
& & ! g_pXWaylandManager - > shouldBeFloated ( pWindow ) ) { // don't group XWayland windows that should be floated.
switch ( pWindow - > m_bIsFloating ) {
case false :
if ( g_pCompositor - > m_pLastWindow - > m_bIsFloating )
pWindow - > m_bIsFloating = true ;
break ;
case true :
if ( ! g_pCompositor - > m_pLastWindow - > m_bIsFloating )
pWindow - > m_bIsFloating = false ;
break ;
}
static auto USECURRPOS = CConfigValue < Hyprlang : : INT > ( " group:insert_after_current " ) ;
( * USECURRPOS ? g_pCompositor - > m_pLastWindow : g_pCompositor - > m_pLastWindow - > getGroupTail ( ) ) - > insertWindowToGroup ( pWindow ) ;
g_pCompositor - > m_pLastWindow - > setGroupCurrent ( pWindow ) ;
pWindow - > applyGroupRules ( ) ;
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
2022-06-30 12:09:05 +02:00
if ( DRAGGINGWINDOW - > m_bDraggingTiled ) {
DRAGGINGWINDOW - > m_bIsFloating = false ;
2022-11-08 20:28:41 +00:00
g_pInputManager - > refocus ( ) ;
2022-06-30 12:09:05 +02:00
changeWindowFloatingMode ( DRAGGINGWINDOW ) ;
2023-05-29 18:05:41 +02:00
DRAGGINGWINDOW - > m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize ;
2023-11-19 12:29:01 +00:00
} else if ( g_pInputManager - > dragMode = = MBIND_MOVE ) {
g_pHyprRenderer - > damageWindow ( DRAGGINGWINDOW ) ;
const auto MOUSECOORDS = g_pInputManager - > getMouseCoordsInternal ( ) ;
2024-04-27 12:43:12 +01:00
PHLWINDOW pWindow = g_pCompositor - > vectorToWindowUnified ( MOUSECOORDS , RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY , 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-04-27 12:43:12 +01:00
if ( pWindow - > m_sGroupData . pNextWindow . lock ( ) & & DRAGGINGWINDOW - > canBeGroupedInto ( pWindow ) ) {
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 ) ;
DRAGGINGWINDOW - > updateWindowDecos ( ) ;
if ( ! DRAGGINGWINDOW - > getDecorationByType ( DECORATION_GROUPBAR ) )
DRAGGINGWINDOW - > addWindowDeco ( std : : make_unique < CHyprGroupBarDecoration > ( DRAGGINGWINDOW ) ) ;
}
}
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
}
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-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-03-02 01:35:17 +01:00
CBox wb = { m_vBeginDragPositionXY + DELTA , DRAGGINGWINDOW - > m_vRealSize . goal ( ) } ;
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-07-11 14:10:42 +00:00
Vector2D MINSIZE = g_pXWaylandManager - > getMinSizeForWindow ( DRAGGINGWINDOW ) . clamp ( DRAGGINGWINDOW - > m_sWindowData . minSize . valueOr ( Vector2D ( 20 , 20 ) ) ) ;
Vector2D MAXSIZE ;
if ( DRAGGINGWINDOW - > m_sWindowData . maxSize . hasValue ( ) )
MAXSIZE = g_pXWaylandManager - > getMaxSizeForWindow ( DRAGGINGWINDOW ) . clamp ( { } , DRAGGINGWINDOW - > m_sWindowData . maxSize . value ( ) ) ;
else
MAXSIZE = g_pXWaylandManager - > getMaxSizeForWindow ( DRAGGINGWINDOW ) . 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 ) ;
if ( ( m_vBeginDragSizeXY . x > = 1 & & m_vBeginDragSizeXY . y > = 1 ) & &
( g_pInputManager - > dragMode = = MBIND_RESIZE_FORCE_RATIO | |
2024-07-11 14:10:42 +00:00
( ! ( g_pInputManager - > dragMode = = MBIND_RESIZE_BLOCK_RATIO ) & & DRAGGINGWINDOW - > m_sWindowData . keepAspectRatio . valueOrDefault ( ) ) ) ) {
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
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 ) {
2022-06-30 12:09:05 +02:00
DRAGGINGWINDOW - > m_iMonitorID = PMONITOR - > ID ;
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-03-02 01:35:17 +01:00
const auto PNEWMON = g_pCompositor - > getMonitorFromVector ( pWindow - > m_vRealPosition . value ( ) + pWindow - > m_vRealSize . value ( ) / 2.f ) ;
2022-06-30 12:09:05 +02:00
pWindow - > m_iMonitorID = PNEWMON - > ID ;
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-07-31 17:55:52 +00:00
g_pCompositor - > setWindowFullscreenInternal ( g_pCompositor - > getFullscreenWindowOnWorkspace ( PWORKSPACE - > m_iID ) , 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 ;
2022-10-19 21:32:30 +01:00
// move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back.
pWindow - > m_vPosition = Vector2D ( - 999999 , - 999999 ) ;
2022-06-30 12:09:05 +02:00
onWindowCreatedTiling ( pWindow ) ;
pWindow - > m_vRealPosition . setValue ( PSAVEDPOS ) ;
pWindow - > m_vRealSize . setValue ( PSAVEDSIZE ) ;
// fix pseudo leaving artifacts
g_pHyprRenderer - > damageMonitor ( g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ) ;
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
2022-07-08 21:52:52 +02:00
g_pHyprRenderer - > damageMonitor ( g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ) ;
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-04-02 20:32:39 +01:00
return g_pCompositor - > getFullscreenWindowOnWorkspace ( pWindow - > workspaceID ( ) ) ;
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-04-02 20:32:39 +01:00
pWindowCandidate = g_pCompositor - > getTopLeftWindowOnWorkspace ( pWindow - > workspaceID ( ) ) ;
2023-12-12 16:44:31 +00:00
if ( ! pWindowCandidate )
2024-04-02 20:32:39 +01:00
pWindowCandidate = g_pCompositor - > getFirstWindowOnWorkspace ( pWindow - > workspaceID ( ) ) ;
2023-12-12 16:44:31 +00:00
if ( ! pWindowCandidate | | pWindow = = pWindowCandidate | | ! pWindowCandidate - > m_bIsMapped | | pWindowCandidate - > isHidden ( ) | | pWindowCandidate - > m_bX11ShouldntFocus | |
2024-08-30 14:12:23 +02:00
pWindowCandidate - > isX11OverrideRedirect ( ) | | pWindowCandidate - > m_iMonitorID ! = g_pCompositor - > m_pLastMonitor - > ID )
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-03-29 00:43:50 +00:00
if ( r . szRule . starts_with ( " size " ) ) {
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 ) ;
const auto MAXSIZE = g_pXWaylandManager - > getMaxSizeForWindow ( pWindow ) ;
const auto SIZEX = SIZEXSTR = = " max " ?
std : : clamp ( MAXSIZE . x , 20.0 , g_pCompositor - > m_pLastMonitor - > vecSize . x ) :
( ! SIZEXSTR . contains ( ' % ' ) ? std : : stoi ( SIZEXSTR ) : std : : stof ( SIZEXSTR . substr ( 0 , SIZEXSTR . length ( ) - 1 ) ) * 0.01 * g_pCompositor - > m_pLastMonitor - > vecSize . x ) ;
const auto SIZEY = SIZEYSTR = = " max " ?
std : : clamp ( MAXSIZE . y , 20.0 , g_pCompositor - > m_pLastMonitor - > vecSize . y ) :
( ! SIZEYSTR . contains ( ' % ' ) ? std : : stoi ( SIZEYSTR ) : std : : stof ( SIZEYSTR . substr ( 0 , SIZEYSTR . length ( ) - 1 ) ) * 0.01 * g_pCompositor - > m_pLastMonitor - > vecSize . y ) ;
sizeOverride = { SIZEX , SIZEY } ;
} catch ( . . . ) { Debug : : log ( LOG , " Rule size failed, rule: {} -> {} " , r . szRule , r . szValue ) ; }
break ;
}
}
}
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-03-29 00:43:50 +00:00
if ( r . szRule . starts_with ( " float " ) ) {
shouldBeFloated = true ;
break ;
}
}
}
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
}
2022-12-16 17:17:31 +00:00
IHyprLayout : : ~ IHyprLayout ( ) { }