2023-04-17 00:53:02 -07:00
# include "globals.hpp"
2023-04-12 01:33:00 -07:00
# include "Hy3Layout.hpp"
2023-04-13 14:12:48 -07:00
2023-04-12 01:33:00 -07:00
# include <src/Compositor.hpp>
Hy3GroupData : : Hy3GroupData ( Hy3GroupLayout layout ) : layout ( layout ) { }
Hy3NodeData : : Hy3NodeData ( ) : Hy3NodeData ( ( CWindow * ) nullptr ) { }
Hy3NodeData : : Hy3NodeData ( CWindow * window ) : type ( Hy3NodeData : : Window ) {
this - > as_window = window ;
}
Hy3NodeData : : Hy3NodeData ( Hy3GroupData group ) : type ( Hy3NodeData : : Group ) {
new ( & this - > as_group ) Hy3GroupData ( std : : move ( group ) ) ;
}
2023-04-13 14:12:48 -07:00
Hy3NodeData : : Hy3NodeData ( Hy3GroupLayout layout ) : Hy3NodeData ( Hy3GroupData ( layout ) ) { }
2023-04-12 01:33:00 -07:00
Hy3NodeData : : ~ Hy3NodeData ( ) {
switch ( this - > type ) {
case Hy3NodeData : : Window :
break ;
case Hy3NodeData : : Group :
this - > as_group . ~ Hy3GroupData ( ) ;
// who ever thought calling the dtor after a move was a good idea?
this - > type = Hy3NodeData : : Window ;
break ;
}
}
Hy3NodeData : : Hy3NodeData ( const Hy3NodeData & from ) : type ( from . type ) {
Debug : : log ( LOG , " Copy CTor type matches? %d is group? %d " , this - > type = = from . type , this - > type = = Hy3NodeData : : Group ) ;
switch ( from . type ) {
case Hy3NodeData : : Window :
this - > as_window = from . as_window ;
break ;
case Hy3NodeData : : Group :
new ( & this - > as_group ) Hy3GroupData ( from . as_group ) ;
break ;
}
}
Hy3NodeData : : Hy3NodeData ( Hy3NodeData & & from ) : type ( from . type ) {
Debug : : log ( LOG , " Move CTor type matches? %d is group? %d " , this - > type = = from . type , this - > type = = Hy3NodeData : : Group ) ;
switch ( from . type ) {
case Hy3NodeData : : Window :
this - > as_window = from . as_window ;
break ;
case Hy3NodeData : : Group :
new ( & this - > as_group ) Hy3GroupData ( std : : move ( from . as_group ) ) ;
break ;
}
}
Hy3NodeData & Hy3NodeData : : operator = ( const Hy3NodeData & from ) {
Debug : : log ( LOG , " operator= type matches? %d is group? %d " , this - > type = = from . type , this - > type = = Hy3NodeData : : Group ) ;
if ( this - > type = = Hy3NodeData : : Group ) {
this - > as_group . ~ Hy3GroupData ( ) ;
}
this - > type = from . type ;
switch ( this - > type ) {
case Hy3NodeData : : Window :
this - > as_window = from . as_window ;
break ;
case Hy3NodeData : : Group :
new ( & this - > as_group ) Hy3GroupData ( from . as_group ) ;
break ;
}
return * this ;
}
2023-04-13 14:12:48 -07:00
Hy3NodeData & Hy3NodeData : : operator = ( CWindow * window ) {
* this = Hy3NodeData ( window ) ;
return * this ;
}
Hy3NodeData & Hy3NodeData : : operator = ( Hy3GroupLayout layout ) {
* this = Hy3NodeData ( layout ) ;
return * this ;
}
2023-04-12 01:33:00 -07:00
bool Hy3NodeData : : operator = = ( const Hy3NodeData & rhs ) const {
if ( this - > type ! = rhs . type ) return false ;
switch ( this - > type ) {
case Hy3NodeData : : Window :
return this - > as_window = = rhs . as_window ;
case Hy3NodeData : : Group :
return this - > as_group . children = = rhs . as_group . children ;
}
return false ;
}
bool Hy3Node : : operator = = ( const Hy3Node & rhs ) const {
return this - > data = = rhs . data ;
}
void Hy3Node : : recalcSizePosRecursive ( bool force ) {
if ( this - > data . type ! = Hy3NodeData : : Group ) {
this - > layout - > applyNodeDataToWindow ( this , force ) ;
return ;
}
auto * group = & this - > data . as_group ;
2023-04-12 03:33:45 -07:00
if ( group - > children . size ( ) = = 1 & & this - > parent ! = nullptr ) {
2023-04-16 21:56:19 -07:00
auto child = group - > children . front ( ) ;
if ( child = = this ) {
Debug : : log ( ERR , " a group (%p) has become its own child " , this ) ;
}
2023-04-12 03:33:45 -07:00
double distortOut ;
double distortIn ;
const auto * gaps_in = & g_pConfigManager - > getConfigValuePtr ( " general:gaps_in " ) - > intValue ;
const auto * gaps_out = & g_pConfigManager - > getConfigValuePtr ( " general:gaps_out " ) - > intValue ;
if ( gaps_in > gaps_out ) {
distortOut = * gaps_out - 1.0 ;
} else {
distortOut = * gaps_in - 1.0 ;
}
if ( distortOut < 0 ) distortOut = 0.0 ;
distortIn = * gaps_in * 2 ;
switch ( group - > layout ) {
case Hy3GroupLayout : : SplitH :
child - > position . x = this - > position . x - distortOut ;
child - > size . x = this - > size . x - distortIn ;
child - > position . y = this - > position . y ;
child - > size . y = this - > size . y ;
break ;
case Hy3GroupLayout : : SplitV :
child - > position . y = this - > position . y - distortOut ;
child - > size . y = this - > size . y - distortIn ;
child - > position . x = this - > position . x ;
child - > size . x = this - > size . x ;
case Hy3GroupLayout : : Tabbed :
// TODO
break ;
}
2023-04-18 23:41:18 -07:00
child - > recalcSizePosRecursive ( force ) ;
2023-04-12 03:33:45 -07:00
return ;
}
2023-04-12 01:33:00 -07:00
int constraint ;
switch ( group - > layout ) {
case Hy3GroupLayout : : SplitH :
constraint = this - > size . x ;
break ;
case Hy3GroupLayout : : SplitV :
constraint = this - > size . y ;
break ;
case Hy3GroupLayout : : Tabbed :
break ;
}
2023-04-18 23:41:18 -07:00
double ratio_mul = group - > layout ! = Hy3GroupLayout : : Tabbed ? group - > children . empty ( ) ? 0 : constraint / group - > children . size ( ) : 0 ;
2023-04-12 01:33:00 -07:00
double offset = 0 ;
for ( auto child : group - > children ) {
switch ( group - > layout ) {
case Hy3GroupLayout : : SplitH :
child - > position . x = this - > position . x + offset ;
2023-04-18 23:41:18 -07:00
child - > size . x = child - > size_ratio * ratio_mul ;
2023-04-12 01:33:00 -07:00
offset + = child - > size . x ;
child - > position . y = this - > position . y ;
child - > size . y = this - > size . y ;
break ;
case Hy3GroupLayout : : SplitV :
child - > position . y = this - > position . y + offset ;
2023-04-18 23:41:18 -07:00
child - > size . y = child - > size_ratio * ratio_mul ;
2023-04-12 01:33:00 -07:00
offset + = child - > size . y ;
child - > position . x = this - > position . x ;
child - > size . x = this - > size . x ;
break ;
case Hy3GroupLayout : : Tabbed :
// TODO: tab bars
child - > position = this - > position ;
child - > size = this - > size ;
break ;
}
child - > recalcSizePosRecursive ( force ) ;
}
}
2023-04-23 21:02:51 -07:00
bool Hy3Node : : swallowGroups ( Hy3Node * into ) {
2023-04-19 19:53:50 -07:00
if ( into = = nullptr
| | into - > parent = = nullptr
| | into - > data . type ! = Hy3NodeData : : Group
| | into - > data . as_group . children . size ( ) ! = 1 )
return false ;
2023-04-19 02:07:47 -07:00
auto * child = into - > data . as_group . children . front ( ) ;
Debug : : log ( LOG , " Swallowing %p into %p " , child , into ) ;
2023-04-23 21:02:51 -07:00
Hy3Node : : swapData ( * into , * child ) ;
2023-04-19 02:07:47 -07:00
into - > layout - > nodes . remove ( * child ) ;
return true ;
}
2023-04-23 21:02:51 -07:00
Hy3Node * Hy3Node : : removeFromParentRecursive ( ) {
Hy3Node * parent = this ;
2023-04-22 04:19:34 -07:00
2023-04-23 21:02:51 -07:00
Debug : : log ( LOG , " Recursively removing parent nodes of %p " , parent ) ;
2023-04-22 04:19:34 -07:00
while ( parent - > parent ! = nullptr ) {
auto * child = parent ;
parent = parent - > parent ;
auto & group = parent - > data . as_group ;
if ( group . children . size ( ) > 2 ) {
auto iter = std : : find ( group . children . begin ( ) , group . children . end ( ) , child ) ;
if ( iter = = group . children . begin ( ) ) {
group . lastFocusedChild = * std : : next ( iter ) ;
} else {
group . lastFocusedChild = * std : : prev ( iter ) ;
}
}
group . children . remove ( child ) ;
if ( group . children . size ( ) = = 1 ) {
group . lastFocusedChild = group . children . front ( ) ;
}
2023-04-23 21:02:51 -07:00
if ( child ! = this ) {
2023-04-22 04:19:34 -07:00
parent - > layout - > nodes . remove ( * child ) ;
}
if ( ! group . children . empty ( ) ) {
auto splitmod = group . children . empty ( ) ? 0.0 : - ( ( 1.0 - child - > size_ratio ) / group . children . size ( ) ) ;
for ( auto * child : group . children ) {
child - > size_ratio + = splitmod ;
}
break ;
}
}
return parent ;
}
2023-04-13 14:12:48 -07:00
bool Hy3GroupData : : hasChild ( Hy3Node * node ) {
Debug : : log ( LOG , " Searching for child %p of %p " , this , node ) ;
for ( auto child : this - > children ) {
if ( child = = node ) return true ;
if ( child - > data . type = = Hy3NodeData : : Group ) {
if ( child - > data . as_group . hasChild ( node ) ) return true ;
}
}
return false ;
}
2023-04-23 21:02:51 -07:00
void Hy3Node : : swapData ( Hy3Node & a , Hy3Node & b ) {
2023-04-13 14:12:48 -07:00
Hy3NodeData aData = std : : move ( a . data ) ;
a . data = b . data ;
b . data = aData ;
if ( a . data . type = = Hy3NodeData : : Group ) {
for ( auto child : a . data . as_group . children ) {
child - > parent = & a ;
}
}
if ( b . data . type = = Hy3NodeData : : Group ) {
for ( auto child : b . data . as_group . children ) {
child - > parent = & b ;
}
}
}
2023-04-12 01:33:00 -07:00
int Hy3Layout : : getWorkspaceNodeCount ( const int & id ) {
int count = 0 ;
for ( auto & node : this - > nodes ) {
if ( node . workspace_id = = id & & node . valid ) count + + ;
}
return count ;
}
Hy3Node * Hy3Layout : : getNodeFromWindow ( CWindow * window ) {
for ( auto & node : this - > nodes ) {
if ( node . data . type = = Hy3NodeData : : Window & & node . data . as_window = = window ) {
return & node ;
}
}
return nullptr ;
}
Hy3Node * Hy3Layout : : getWorkspaceRootGroup ( const int & id ) {
for ( auto & node : this - > nodes ) {
2023-04-18 00:15:32 -07:00
if ( node . workspace_id = = id & & node . parent = = nullptr & & node . data . type = = Hy3NodeData : : Group ) {
2023-04-12 01:33:00 -07:00
return & node ;
}
}
return nullptr ;
}
void Hy3Layout : : applyNodeDataToWindow ( Hy3Node * node , bool force ) {
if ( node - > data . type ! = Hy3NodeData : : Window ) return ;
CWindow * window = node - > data . as_window ;
CMonitor * monitor = nullptr ;
if ( g_pCompositor - > isWorkspaceSpecial ( node - > workspace_id ) ) {
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( m - > specialWorkspaceID = = node - > workspace_id ) {
monitor = m . get ( ) ;
break ;
}
}
} else {
monitor = g_pCompositor - > getMonitorFromID ( g_pCompositor - > getWorkspaceByID ( node - > workspace_id ) - > m_iMonitorID ) ;
}
if ( monitor = = nullptr ) {
Debug : : log ( ERR , " Orphaned Node %x (workspace ID: %i)!! " , node , node - > workspace_id ) ;
return ;
}
// for gaps outer
const bool display_left = STICKS ( node - > position . x , monitor - > vecPosition . x + monitor - > vecReservedTopLeft . x ) ;
const bool display_right = STICKS ( node - > position . x + node - > size . x , monitor - > vecPosition . x + monitor - > vecSize . x - monitor - > vecReservedBottomRight . x ) ;
const bool display_top = STICKS ( node - > position . y , monitor - > vecPosition . y + monitor - > vecReservedTopLeft . y ) ;
const bool display_bottom = STICKS ( node - > position . y + node - > size . y , monitor - > vecPosition . y + monitor - > vecSize . y - monitor - > vecReservedBottomRight . y ) ;
const auto * border_size = & g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
const auto * gaps_in = & g_pConfigManager - > getConfigValuePtr ( " general:gaps_in " ) - > intValue ;
const auto * gaps_out = & g_pConfigManager - > getConfigValuePtr ( " general:gaps_out " ) - > intValue ;
2023-04-17 00:53:02 -07:00
static auto * const single_window_no_gaps = & HyprlandAPI : : getConfigValue ( PHANDLE , " plugin:hy3:no_gaps_when_only " ) - > intValue ;
2023-04-12 01:33:00 -07:00
if ( ! g_pCompositor - > windowExists ( window ) | | ! window - > m_bIsMapped ) {
Debug : : log ( ERR , " Node %p holding invalid window %p!! " , node , window ) ;
this - > onWindowRemovedTiling ( window ) ;
return ;
}
window - > m_vSize = node - > size ;
window - > m_vPosition = node - > position ;
auto calcPos = window - > m_vPosition + Vector2D ( * border_size , * border_size ) ;
auto calcSize = window - > m_vSize - Vector2D ( 2 * * border_size , 2 * * border_size ) ;
const auto workspace_node_count = this - > getWorkspaceNodeCount ( window - > m_iWorkspaceID ) ;
if ( * single_window_no_gaps
& & ! g_pCompositor - > isWorkspaceSpecial ( window - > m_iWorkspaceID )
& & ( workspace_node_count = = 1
| | ( window - > m_bIsFullscreen
& & g_pCompositor - > getWorkspaceByID ( window - > m_iWorkspaceID ) - > m_efFullscreenMode = = FULLSCREEN_MAXIMIZED ) ) )
{
window - > m_vRealPosition = window - > m_vPosition ;
window - > m_vRealSize = window - > m_vSize ;
window - > updateWindowDecos ( ) ;
window - > m_sSpecialRenderData . rounding = false ;
window - > m_sSpecialRenderData . border = false ;
window - > m_sSpecialRenderData . decorate = false ;
} else {
window - > m_sSpecialRenderData . rounding = true ;
window - > m_sSpecialRenderData . border = true ;
window - > m_sSpecialRenderData . decorate = true ;
Vector2D offset_topleft (
display_left ? * gaps_out : * gaps_in ,
display_top ? * gaps_out : * gaps_in
) ;
Vector2D offset_bottomright (
display_right ? * gaps_out : * gaps_in ,
display_bottom ? * gaps_out : * gaps_in
) ;
calcPos = calcPos + offset_topleft ;
calcSize = calcSize - offset_topleft - offset_bottomright ;
const auto reserved_area = window - > getFullWindowReservedArea ( ) ;
calcPos = calcPos + reserved_area . topLeft ;
calcSize = calcSize - ( reserved_area . topLeft - reserved_area . bottomRight ) ;
window - > m_vRealPosition = calcPos ;
window - > m_vRealSize = calcSize ;
Debug : : log ( LOG , " Set size (%f %f) " , calcSize . x , calcSize . y ) ;
g_pXWaylandManager - > setWindowSize ( window , calcSize ) ;
if ( force ) {
g_pHyprRenderer - > damageWindow ( window ) ;
window - > m_vRealPosition . warp ( ) ;
2023-04-18 23:41:18 -07:00
window - > m_vRealSize . warp ( ) ;
2023-04-12 01:33:00 -07:00
g_pHyprRenderer - > damageWindow ( window ) ;
}
window - > updateWindowDecos ( ) ;
}
}
void Hy3Layout : : onWindowCreatedTiling ( CWindow * window ) {
if ( window - > m_bIsFloating ) return ;
2023-04-18 00:15:32 -07:00
auto * existing = this - > getNodeFromWindow ( window ) ;
if ( existing ! = nullptr ) {
Debug : : log ( WARN , " Attempted to add a window(%p) that is already tiled(as %p) to the layout " , window , existing ) ;
return ;
}
2023-04-12 01:33:00 -07:00
auto * monitor = g_pCompositor - > getMonitorFromID ( window - > m_iMonitorID ) ;
Hy3Node * opening_into ;
Hy3Node * opening_after ;
if ( g_pCompositor - > m_pLastWindow ! = nullptr
& & ! g_pCompositor - > m_pLastWindow - > m_bIsFloating
& & g_pCompositor - > m_pLastWindow ! = window
& & g_pCompositor - > m_pLastWindow - > m_iWorkspaceID = = window - > m_iWorkspaceID
& & g_pCompositor - > m_pLastWindow - > m_bIsMapped )
{
opening_after = this - > getNodeFromWindow ( g_pCompositor - > m_pLastWindow ) ;
} else {
opening_after = this - > getNodeFromWindow ( g_pCompositor - > vectorToWindowTiled ( g_pInputManager - > getMouseCoordsInternal ( ) ) ) ;
}
2023-04-18 00:15:32 -07:00
if ( opening_after ! = nullptr & & opening_after - > workspace_id ! = window - > m_iWorkspaceID ) {
opening_after = nullptr ;
}
2023-04-12 01:33:00 -07:00
if ( opening_after ! = nullptr ) {
opening_into = opening_after - > parent ;
} else {
if ( ( opening_into = this - > getWorkspaceRootGroup ( window - > m_iWorkspaceID ) ) = = nullptr ) {
this - > nodes . push_back ( {
2023-04-13 14:12:48 -07:00
. data = Hy3GroupLayout : : SplitH ,
2023-04-21 21:53:03 -07:00
. position = monitor - > vecPosition + monitor - > vecReservedTopLeft ,
. size = monitor - > vecSize - monitor - > vecReservedTopLeft - monitor - > vecReservedBottomRight ,
2023-04-12 01:33:00 -07:00
. workspace_id = window - > m_iWorkspaceID ,
. layout = this ,
} ) ;
opening_into = & this - > nodes . back ( ) ;
}
}
if ( opening_into - > data . type ! = Hy3NodeData : : Group ) {
Debug : : log ( ERR , " opening_into node %p was not of type Group " , opening_into ) ;
return ;
}
2023-04-18 00:15:32 -07:00
if ( opening_into - > workspace_id ! = window - > m_iWorkspaceID ) {
Debug : : log ( WARN , " opening_into node %p has workspace %d which does not match the opening window (workspace %d) " , opening_into , opening_into - > workspace_id , window - > m_iWorkspaceID ) ;
}
2023-04-12 01:33:00 -07:00
this - > nodes . push_back ( {
. parent = opening_into ,
2023-04-13 14:12:48 -07:00
. data = window ,
2023-04-12 01:33:00 -07:00
. workspace_id = window - > m_iWorkspaceID ,
. layout = this ,
} ) ;
auto & node = this - > nodes . back ( ) ;
if ( opening_after = = nullptr ) {
opening_into - > data . as_group . children . push_back ( & node ) ;
} else {
auto & children = opening_into - > data . as_group . children ;
auto iter = std : : find ( children . begin ( ) , children . end ( ) , opening_after ) ;
auto iter2 = std : : next ( iter ) ;
children . insert ( iter2 , & node ) ;
}
2023-04-18 00:15:32 -07:00
Debug : : log ( LOG , " opened new window %p(node: %p) on window %p in %p " , window , & node , opening_after , opening_into ) ;
2023-04-12 01:33:00 -07:00
2023-04-16 23:53:22 -07:00
opening_into - > data . as_group . lastFocusedChild = & node ;
2023-04-12 01:33:00 -07:00
opening_into - > recalcSizePosRecursive ( ) ;
2023-04-16 21:56:19 -07:00
Debug : : log ( LOG , " opening_into (%p) contains new child (%p)? %d " , opening_into , & node , opening_into - > data . as_group . hasChild ( & node ) ) ;
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : onWindowRemovedTiling ( CWindow * window ) {
auto * node = this - > getNodeFromWindow ( window ) ;
Debug : : log ( LOG , " remove tiling %p (window %p) " , node , window ) ;
if ( node = = nullptr ) {
Debug : : log ( ERR , " onWindowRemovedTiling node null? " ) ;
return ;
}
window - > m_sSpecialRenderData . rounding = true ;
window - > m_sSpecialRenderData . border = true ;
window - > m_sSpecialRenderData . decorate = true ;
if ( window - > m_bIsFullscreen ) {
g_pCompositor - > setWindowFullscreen ( window , false , FULLSCREEN_FULL ) ;
}
2023-04-23 21:02:51 -07:00
auto * parent = node - > removeFromParentRecursive ( ) ;
2023-04-12 01:33:00 -07:00
this - > nodes . remove ( * node ) ;
2023-04-16 21:56:19 -07:00
if ( parent ! = nullptr ) {
parent - > recalcSizePosRecursive ( ) ;
2023-04-19 18:22:11 -07:00
2023-04-19 21:11:36 -07:00
if ( parent - > data . as_group . children . size ( ) = = 1
& & parent - > data . as_group . children . front ( ) - > data . type = = Hy3NodeData : : Group )
{
auto * target_parent = parent ;
2023-04-23 21:02:51 -07:00
while ( target_parent ! = nullptr & & Hy3Node : : swallowGroups ( target_parent ) ) {
2023-04-19 21:11:36 -07:00
target_parent = target_parent - > parent ;
}
if ( target_parent ! = parent & & target_parent ! = nullptr )
target_parent - > recalcSizePosRecursive ( ) ;
}
2023-04-19 18:22:11 -07:00
}
2023-04-12 01:33:00 -07:00
}
2023-04-16 23:53:22 -07:00
CWindow * Hy3Layout : : getNextWindowCandidate ( CWindow * window ) {
auto * node = this - > getWorkspaceRootGroup ( window - > m_iWorkspaceID ) ;
if ( node = = nullptr ) return nullptr ;
2023-04-22 02:39:51 -07:00
while ( node - > data . type = = Hy3NodeData : : Group ) {
node = node - > data . as_group . lastFocusedChild ;
if ( node = = nullptr ) {
Debug : : log ( ERR , " A group's last focused child was null when getting the next selection candidate " ) ;
return nullptr ;
}
}
2023-04-16 23:53:22 -07:00
return node - > data . as_window ;
}
2023-04-12 03:33:45 -07:00
void Hy3Layout : : onWindowFocusChange ( CWindow * window ) {
2023-04-23 14:12:34 -07:00
Debug : : log ( LOG , " Switched windows from to %p " , window ) ;
auto * node = this - > getNodeFromWindow ( window ) ;
2023-04-19 21:17:48 -07:00
if ( node = = nullptr ) return ;
2023-04-12 03:33:45 -07:00
2023-04-19 21:17:48 -07:00
while ( node - > parent ! = nullptr ) {
node - > parent - > data . as_group . lastFocusedChild = node ;
node = node - > parent ;
}
2023-04-12 03:33:45 -07:00
}
2023-04-12 01:33:00 -07:00
bool Hy3Layout : : isWindowTiled ( CWindow * window ) {
return this - > getNodeFromWindow ( window ) ! = nullptr ;
}
2023-04-17 00:53:02 -07:00
void Hy3Layout : : recalculateMonitor ( const int & monitor_id ) {
2023-04-19 20:59:06 -07:00
Debug : : log ( LOG , " Recalculate monitor %d " , monitor_id ) ;
2023-04-17 00:53:02 -07:00
const auto monitor = g_pCompositor - > getMonitorFromID ( monitor_id ) ;
if ( monitor = = nullptr ) return ;
2023-04-19 20:59:06 -07:00
g_pHyprRenderer - > damageMonitor ( monitor ) ;
2023-04-17 00:53:02 -07:00
const auto workspace = g_pCompositor - > getWorkspaceByID ( monitor - > activeWorkspace ) ;
if ( workspace = = nullptr ) return ;
if ( monitor - > specialWorkspaceID ) {
const auto top_node = this - > getWorkspaceRootGroup ( monitor - > specialWorkspaceID ) ;
if ( top_node ! = nullptr ) {
top_node - > position = monitor - > vecPosition + monitor - > vecReservedTopLeft ;
top_node - > size = monitor - > vecSize - monitor - > vecReservedTopLeft - monitor - > vecReservedBottomRight ;
top_node - > recalcSizePosRecursive ( ) ;
}
}
if ( workspace - > m_bHasFullscreenWindow ) {
const auto window = g_pCompositor - > getFullscreenWindowOnWorkspace ( workspace - > m_iID ) ;
if ( workspace - > m_efFullscreenMode = = FULLSCREEN_FULL ) {
window - > m_vRealPosition = monitor - > vecPosition ;
window - > m_vRealSize = monitor - > vecSize ;
} else {
// Vaxry's hack from below, but again
Hy3Node fakeNode = {
. data = window ,
. position = monitor - > vecPosition + monitor - > vecReservedTopLeft ,
. size = monitor - > vecSize - monitor - > vecReservedTopLeft - monitor - > vecReservedBottomRight ,
. workspace_id = window - > m_iWorkspaceID ,
} ;
this - > applyNodeDataToWindow ( & fakeNode ) ;
}
} else {
2023-04-19 20:59:06 -07:00
const auto top_node = this - > getWorkspaceRootGroup ( monitor - > activeWorkspace ) ;
2023-04-17 00:53:02 -07:00
2023-04-19 20:59:06 -07:00
if ( top_node ! = nullptr ) {
2023-04-17 00:53:02 -07:00
top_node - > position = monitor - > vecPosition + monitor - > vecReservedTopLeft ;
top_node - > size = monitor - > vecSize - monitor - > vecReservedTopLeft - monitor - > vecReservedBottomRight ;
top_node - > recalcSizePosRecursive ( ) ;
}
}
2023-04-12 01:33:00 -07:00
}
2023-04-19 20:59:06 -07:00
void Hy3Layout : : recalculateWindow ( CWindow * window ) {
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node = = nullptr ) return ;
node - > recalcSizePosRecursive ( ) ;
2023-04-12 01:33:00 -07:00
}
2023-04-18 23:41:18 -07:00
void Hy3Layout : : onBeginDragWindow ( ) {
this - > drag_flags . started = false ;
IHyprLayout : : onBeginDragWindow ( ) ;
}
2023-04-12 01:33:00 -07:00
void Hy3Layout : : resizeActiveWindow ( const Vector2D & delta , CWindow * pWindow ) {
2023-04-18 23:41:18 -07:00
auto window = pWindow ? pWindow : g_pCompositor - > m_pLastWindow ;
if ( ! g_pCompositor - > windowValidMapped ( window ) ) return ;
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node = = nullptr ) return ;
if ( ! this - > drag_flags . started ) {
auto mouse = g_pInputManager - > getMouseCoordsInternal ( ) ;
auto mouseOffset = mouse - window - > m_vPosition ;
this - > drag_flags = {
. started = true ,
. xExtent = mouseOffset . x > window - > m_vSize . x / 2 ,
. yExtent = mouseOffset . y > window - > m_vSize . y / 2 ,
} ;
Debug : : log ( LOG , " Positive offsets - x: %d, y: %d " , this - > drag_flags . xExtent , this - > drag_flags . yExtent ) ;
}
const auto animate = & g_pConfigManager - > getConfigValuePtr ( " misc:animate_manual_resizes " ) - > intValue ;
auto monitor = g_pCompositor - > getMonitorFromID ( window - > m_iMonitorID ) ;
const bool display_left = STICKS ( node - > position . x , monitor - > vecPosition . x + monitor - > vecReservedTopLeft . x ) ;
const bool display_right = STICKS ( node - > position . x + node - > size . x , monitor - > vecPosition . x + monitor - > vecSize . x - monitor - > vecReservedBottomRight . x ) ;
const bool display_top = STICKS ( node - > position . y , monitor - > vecPosition . y + monitor - > vecReservedTopLeft . y ) ;
const bool display_bottom = STICKS ( node - > position . y + node - > size . y , monitor - > vecPosition . y + monitor - > vecSize . y - monitor - > vecReservedBottomRight . y ) ;
Vector2D allowed_movement = delta ;
if ( display_left & & display_right ) allowed_movement . x = 0 ;
if ( display_top & & display_bottom ) allowed_movement . y = 0 ;
auto * inner_node = node ;
// break into parent groups when encountering a corner we're dragging in or a tab group
while ( inner_node - > parent ! = nullptr ) {
auto & group = inner_node - > parent - > data . as_group ;
switch ( group . layout ) {
case Hy3GroupLayout : : Tabbed :
// treat tabbed layouts as if they dont exist during resizing
goto cont ;
case Hy3GroupLayout : : SplitH :
if ( ( this - > drag_flags . xExtent & & group . children . back ( ) = = inner_node )
| | ( ! this - > drag_flags . xExtent & & group . children . front ( ) = = inner_node ) ) {
goto cont ;
}
break ;
case Hy3GroupLayout : : SplitV :
if ( ( this - > drag_flags . yExtent & & group . children . back ( ) = = inner_node )
| | ( ! this - > drag_flags . yExtent & & group . children . front ( ) = = inner_node ) ) {
goto cont ;
}
break ;
}
break ;
cont :
inner_node = inner_node - > parent ;
}
auto * inner_parent = inner_node - > parent ;
if ( inner_parent = = nullptr ) return ;
auto * outer_node = inner_node ;
// break into parent groups when encountering a corner we're dragging in, a tab group,
// or a layout matching the inner_parent.
while ( outer_node - > parent ! = nullptr ) {
auto & group = outer_node - > parent - > data . as_group ;
// break out of all layouts that match the orientation of the inner_parent
if ( group . layout = = inner_parent - > data . as_group . layout ) goto cont2 ;
switch ( group . layout ) {
case Hy3GroupLayout : : Tabbed :
// treat tabbed layouts as if they dont exist during resizing
goto cont2 ;
case Hy3GroupLayout : : SplitH :
if ( ( this - > drag_flags . xExtent & & group . children . back ( ) = = outer_node )
| | ( ! this - > drag_flags . xExtent & & group . children . front ( ) = = outer_node ) ) {
goto cont2 ;
}
break ;
case Hy3GroupLayout : : SplitV :
if ( ( this - > drag_flags . yExtent & & group . children . back ( ) = = outer_node )
| | ( ! this - > drag_flags . yExtent & & group . children . front ( ) = = outer_node ) ) {
goto cont2 ;
}
break ;
}
break ;
cont2 :
outer_node = outer_node - > parent ;
}
Debug : : log ( LOG , " resizeActive - inner_node: %p, outer_node: %p " , inner_node , outer_node ) ;
auto & inner_group = inner_parent - > data . as_group ;
// adjust the inner node
switch ( inner_group . layout ) {
case Hy3GroupLayout : : SplitH : {
auto ratio_mod = allowed_movement . x * ( float ) inner_group . children . size ( ) / inner_parent - > size . x ;
auto iter = std : : find ( inner_group . children . begin ( ) , inner_group . children . end ( ) , inner_node ) ;
if ( this - > drag_flags . xExtent ) {
if ( inner_node = = inner_group . children . back ( ) ) break ;
iter = std : : next ( iter ) ;
} else {
if ( inner_node = = inner_group . children . front ( ) ) break ;
iter = std : : prev ( iter ) ;
ratio_mod = - ratio_mod ;
}
auto * neighbor = * iter ;
inner_node - > size_ratio + = ratio_mod ;
neighbor - > size_ratio - = ratio_mod ;
} break ;
case Hy3GroupLayout : : SplitV : {
auto ratio_mod = allowed_movement . y * ( float ) inner_parent - > data . as_group . children . size ( ) / inner_parent - > size . y ;
auto iter = std : : find ( inner_group . children . begin ( ) , inner_group . children . end ( ) , inner_node ) ;
if ( this - > drag_flags . yExtent ) {
if ( inner_node = = inner_group . children . back ( ) ) break ;
iter = std : : next ( iter ) ;
} else {
if ( inner_node = = inner_group . children . front ( ) ) break ;
iter = std : : prev ( iter ) ;
ratio_mod = - ratio_mod ;
}
auto * neighbor = * iter ;
inner_node - > size_ratio + = ratio_mod ;
neighbor - > size_ratio - = ratio_mod ;
} break ;
}
inner_parent - > recalcSizePosRecursive ( * animate = = 0 ) ;
if ( outer_node ! = nullptr & & outer_node - > parent ! = nullptr ) {
auto * outer_parent = outer_node - > parent ;
auto & outer_group = outer_parent - > data . as_group ;
// adjust the outer node
switch ( outer_group . layout ) {
case Hy3GroupLayout : : SplitH : {
auto ratio_mod = allowed_movement . x * ( float ) outer_group . children . size ( ) / outer_parent - > size . x ;
auto iter = std : : find ( outer_group . children . begin ( ) , outer_group . children . end ( ) , outer_node ) ;
if ( this - > drag_flags . xExtent ) {
if ( outer_node = = inner_group . children . back ( ) ) break ;
iter = std : : next ( iter ) ;
} else {
if ( outer_node = = inner_group . children . front ( ) ) break ;
iter = std : : prev ( iter ) ;
ratio_mod = - ratio_mod ;
}
auto * neighbor = * iter ;
outer_node - > size_ratio + = ratio_mod ;
neighbor - > size_ratio - = ratio_mod ;
} break ;
case Hy3GroupLayout : : SplitV : {
auto ratio_mod = allowed_movement . y * ( float ) outer_parent - > data . as_group . children . size ( ) / outer_parent - > size . y ;
auto iter = std : : find ( outer_group . children . begin ( ) , outer_group . children . end ( ) , outer_node ) ;
if ( this - > drag_flags . yExtent ) {
if ( outer_node = = outer_group . children . back ( ) ) break ;
iter = std : : next ( iter ) ;
} else {
if ( outer_node = = outer_group . children . front ( ) ) break ;
iter = std : : prev ( iter ) ;
ratio_mod = - ratio_mod ;
}
auto * neighbor = * iter ;
outer_node - > size_ratio + = ratio_mod ;
neighbor - > size_ratio - = ratio_mod ;
} break ;
}
outer_parent - > recalcSizePosRecursive ( * animate = = 0 ) ;
}
2023-04-12 01:33:00 -07:00
}
2023-04-17 00:53:02 -07:00
void Hy3Layout : : fullscreenRequestForWindow ( CWindow * window , eFullscreenMode fullscreen_mode , bool on ) {
if ( ! g_pCompositor - > windowValidMapped ( window ) ) return ;
if ( on = = window - > m_bIsFullscreen | | g_pCompositor - > isWorkspaceSpecial ( window - > m_iWorkspaceID ) ) return ;
const auto monitor = g_pCompositor - > getMonitorFromID ( window - > m_iMonitorID ) ;
const auto workspace = g_pCompositor - > getWorkspaceByID ( window - > m_iWorkspaceID ) ;
if ( workspace - > m_bHasFullscreenWindow & & on ) return ;
window - > m_bIsFullscreen = on ;
workspace - > m_bHasFullscreenWindow = ! workspace - > m_bHasFullscreenWindow ;
if ( ! window - > m_bIsFullscreen ) {
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node ) {
// restore node positioning if tiled
this - > applyNodeDataToWindow ( node ) ;
} else {
// restore floating position if not
window - > m_vRealPosition = window - > m_vLastFloatingPosition ;
window - > m_vRealSize = window - > m_vLastFloatingSize ;
window - > m_sSpecialRenderData . rounding = true ;
window - > m_sSpecialRenderData . border = true ;
window - > m_sSpecialRenderData . decorate = true ;
}
} else {
workspace - > m_efFullscreenMode = fullscreen_mode ;
// save position and size if floating
if ( window - > m_bIsFloating ) {
window - > m_vLastFloatingPosition = window - > m_vRealPosition . goalv ( ) ;
window - > m_vPosition = window - > m_vRealPosition . goalv ( ) ;
window - > m_vLastFloatingSize = window - > m_vRealSize . goalv ( ) ;
window - > m_vSize = window - > m_vRealSize . goalv ( ) ;
}
if ( fullscreen_mode = = FULLSCREEN_FULL ) {
Debug : : log ( LOG , " fullscreen " ) ;
window - > m_vRealPosition = monitor - > vecPosition ;
window - > m_vRealSize = monitor - > vecSize ;
} else {
Debug : : log ( LOG , " vaxry hack " ) ;
// Copy of vaxry's massive hack
Hy3Node fakeNode = {
. data = window ,
. position = monitor - > vecPosition + monitor - > vecReservedTopLeft ,
. size = monitor - > vecSize - monitor - > vecReservedTopLeft - monitor - > vecReservedBottomRight ,
. workspace_id = window - > m_iWorkspaceID ,
} ;
this - > applyNodeDataToWindow ( & fakeNode ) ;
}
}
g_pCompositor - > updateWindowAnimatedDecorationValues ( window ) ;
g_pXWaylandManager - > setWindowSize ( window , window - > m_vRealSize . goalv ( ) ) ;
g_pCompositor - > moveWindowToTop ( window ) ;
this - > recalculateMonitor ( monitor - > ID ) ;
2023-04-12 01:33:00 -07:00
}
std : : any Hy3Layout : : layoutMessage ( SLayoutMessageHeader header , std : : string content ) {
return " " ;
}
2023-04-19 20:59:06 -07:00
SWindowRenderLayoutHints Hy3Layout : : requestRenderHints ( CWindow * window ) {
return { } ;
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : switchWindows ( CWindow * pWindowA , CWindow * pWindowB ) {
2023-04-19 20:59:06 -07:00
// todo
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : alterSplitRatio ( CWindow * pWindow , float delta , bool exact ) {
2023-04-19 20:59:06 -07:00
// todo
2023-04-12 01:33:00 -07:00
}
std : : string Hy3Layout : : getLayoutName ( ) {
2023-04-19 20:28:05 -07:00
return " hy3 " ;
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : replaceWindowDataWith ( CWindow * from , CWindow * to ) {
2023-04-19 20:59:06 -07:00
auto * node = this - > getNodeFromWindow ( from ) ;
if ( node = = nullptr ) return ;
node - > data . as_window = to ;
this - > applyNodeDataToWindow ( node ) ;
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : onEnable ( ) {
2023-04-19 20:28:05 -07:00
for ( auto & window : g_pCompositor - > m_vWindows ) {
if ( window - > isHidden ( )
| | ! window - > m_bIsMapped
| | window - > m_bFadingOut
| | window - > m_bIsFloating )
continue ;
2023-04-12 01:33:00 -07:00
2023-04-19 20:28:05 -07:00
this - > onWindowCreatedTiling ( window . get ( ) ) ;
}
2023-04-12 01:33:00 -07:00
}
void Hy3Layout : : onDisable ( ) {
2023-04-19 20:28:05 -07:00
this - > nodes . clear ( ) ;
2023-04-12 01:33:00 -07:00
}
2023-04-13 14:12:48 -07:00
void Hy3Layout : : makeGroupOn ( CWindow * window , Hy3GroupLayout layout ) {
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node = = nullptr ) return ;
if ( node - > parent - > data . as_group . children . size ( ) = = 1
& & ( node - > parent - > data . as_group . layout = = Hy3GroupLayout : : SplitH
| | node - > parent - > data . as_group . layout = = Hy3GroupLayout : : SplitV ) )
{
node - > parent - > data . as_group . layout = layout ;
node - > parent - > recalcSizePosRecursive ( ) ;
return ;
}
this - > nodes . push_back ( {
. parent = node ,
. data = node - > data . as_window ,
. workspace_id = node - > workspace_id ,
. layout = this ,
} ) ;
node - > data = layout ;
node - > data . as_group . children . push_back ( & this - > nodes . back ( ) ) ;
2023-04-19 18:19:53 -07:00
node - > data . as_group . lastFocusedChild = & this - > nodes . back ( ) ;
2023-04-13 14:12:48 -07:00
node - > recalcSizePosRecursive ( ) ;
return ;
}
2023-04-16 16:27:18 -07:00
Hy3Node * shiftOrGetFocus ( Hy3Node & node , ShiftDirection direction , bool shift ) ;
void Hy3Layout : : shiftFocus ( CWindow * window , ShiftDirection direction ) {
Debug : : log ( LOG , " ShiftFocus %p %d " , window , direction ) ;
2023-04-13 14:12:48 -07:00
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node = = nullptr ) return ;
2023-04-16 16:27:18 -07:00
Hy3Node * target ;
2023-04-23 21:02:51 -07:00
if ( ( target = Hy3Layout : : shiftOrGetFocus ( * node , direction , false ) ) ) {
2023-04-16 16:27:18 -07:00
g_pCompositor - > focusWindow ( target - > data . as_window ) ;
}
}
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
void Hy3Layout : : shiftWindow ( CWindow * window , ShiftDirection direction ) {
Debug : : log ( LOG , " ShiftWindow %p %d " , window , direction ) ;
auto * node = this - > getNodeFromWindow ( window ) ;
if ( node = = nullptr ) return ;
2023-04-13 14:12:48 -07:00
2023-04-23 21:02:51 -07:00
Hy3Layout : : shiftOrGetFocus ( * node , direction , true ) ;
2023-04-16 16:27:18 -07:00
}
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
bool shiftIsForward ( ShiftDirection direction ) {
return direction = = ShiftDirection : : Right | | direction = = ShiftDirection : : Down ;
}
2023-04-13 14:12:48 -07:00
2023-04-24 01:49:43 -07:00
bool shiftIsVertical ( ShiftDirection direction ) {
return direction = = ShiftDirection : : Up | | direction = = ShiftDirection : : Down ;
}
bool shiftMatchesLayout ( Hy3GroupLayout layout , ShiftDirection direction ) {
return ( layout = = Hy3GroupLayout : : SplitV & & shiftIsVertical ( direction ) )
| | ( layout ! = Hy3GroupLayout : : SplitV & & ! shiftIsVertical ( direction ) ) ;
}
2023-04-13 14:12:48 -07:00
2023-04-24 01:49:43 -07:00
Hy3Node * Hy3Layout : : shiftOrGetFocus ( Hy3Node & node , ShiftDirection direction , bool shift ) {
2023-04-16 16:27:18 -07:00
auto * break_origin = & node ;
auto * break_parent = break_origin - > parent ;
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
// break parents until we hit a container oriented the same way as the shift direction
while ( true ) {
if ( break_parent = = nullptr ) return nullptr ;
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
auto & group = break_parent - > data . as_group ; // must be a group in order to be a parent
2023-04-13 14:12:48 -07:00
2023-04-24 01:49:43 -07:00
if ( shiftMatchesLayout ( group . layout , direction ) ) {
2023-04-16 16:27:18 -07:00
// group has the correct orientation
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
// if this movement would break out of the group, continue the break loop (do not enter this if)
// otherwise break.
if ( ! ( ( ! shiftIsForward ( direction ) & & group . children . front ( ) = = break_origin )
| | ( shiftIsForward ( direction ) & & group . children . back ( ) = = break_origin ) ) )
break ;
2023-04-13 14:12:48 -07:00
}
2023-04-16 16:27:18 -07:00
if ( break_parent - > parent = = nullptr ) {
2023-04-22 02:40:21 -07:00
return nullptr ;
2023-04-16 16:27:18 -07:00
} else {
break_origin = break_parent ;
break_parent = break_origin - > parent ;
}
2023-04-13 14:12:48 -07:00
}
2023-04-16 16:27:18 -07:00
auto & parent_group = break_parent - > data . as_group ;
Hy3Node * target_group = break_parent ;
std : : list < Hy3Node * > : : iterator insert ;
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
if ( break_origin = = parent_group . children . front ( ) & & ! shiftIsForward ( direction ) ) {
if ( ! shift ) return nullptr ;
insert = parent_group . children . begin ( ) ;
} else if ( break_origin = = parent_group . children . back ( ) & & shiftIsForward ( direction ) ) {
if ( ! shift ) return nullptr ;
insert = parent_group . children . end ( ) ;
} else {
auto & group_data = target_group - > data . as_group ;
auto iter = std : : find ( group_data . children . begin ( ) , group_data . children . end ( ) , break_origin ) ;
if ( shiftIsForward ( direction ) ) iter = std : : next ( iter ) ;
else iter = std : : prev ( iter ) ;
if ( ( * iter ) - > data . type = = Hy3NodeData : : Window ) {
if ( shift ) {
if ( target_group = = node . parent ) {
if ( shiftIsForward ( direction ) ) insert = std : : next ( iter ) ;
else insert = iter ;
} else {
if ( shiftIsForward ( direction ) ) insert = iter ;
else insert = std : : next ( iter ) ;
}
} else return * iter ;
} else {
// break into neighboring groups until we hit a window
while ( true ) {
target_group = * iter ;
auto & group_data = target_group - > data . as_group ;
if ( group_data . children . empty ( ) ) return nullptr ; // in theory this would never happen
2023-04-16 21:56:19 -07:00
bool shift_after = false ;
2023-04-24 01:49:43 -07:00
if ( shiftMatchesLayout ( group_data . layout , direction ) ) {
2023-04-16 16:27:18 -07:00
// if the group has the same orientation as movement pick the last/first child based
// on movement direction
if ( shiftIsForward ( direction ) ) iter = group_data . children . begin ( ) ;
2023-04-16 21:56:19 -07:00
else {
iter = std : : prev ( group_data . children . end ( ) ) ;
shift_after = true ;
}
2023-04-16 16:27:18 -07:00
} else {
2023-04-16 21:56:19 -07:00
if ( group_data . lastFocusedChild ! = nullptr ) {
iter = std : : find ( group_data . children . begin ( ) , group_data . children . end ( ) , group_data . lastFocusedChild ) ;
shift_after = true ;
} else {
iter = group_data . children . begin ( ) ;
}
2023-04-16 16:27:18 -07:00
}
if ( ( * iter ) - > data . type = = Hy3NodeData : : Window ) {
if ( shift ) {
2023-04-16 21:56:19 -07:00
if ( shift_after ) insert = std : : next ( iter ) ;
2023-04-16 16:27:18 -07:00
else insert = iter ;
break ;
} else {
return * iter ;
}
2023-04-13 14:12:48 -07:00
}
}
}
2023-04-16 16:27:18 -07:00
}
2023-04-13 14:12:48 -07:00
2023-04-16 16:27:18 -07:00
auto & group_data = target_group - > data . as_group ;
if ( target_group = = node . parent ) {
// nullptr is used as a signal value instead of removing it first to avoid iterator invalidation.
auto iter = std : : find ( group_data . children . begin ( ) , group_data . children . end ( ) , & node ) ;
* iter = nullptr ;
target_group - > data . as_group . children . insert ( insert , & node ) ;
target_group - > data . as_group . children . remove ( nullptr ) ;
target_group - > recalcSizePosRecursive ( ) ;
} else {
target_group - > data . as_group . children . insert ( insert , & node ) ;
2023-04-16 21:56:19 -07:00
// must happen AFTER `insert` is used
2023-04-23 21:02:51 -07:00
auto * old_parent = node . removeFromParentRecursive ( ) ;
2023-04-22 04:19:34 -07:00
node . parent = target_group ;
2023-04-18 23:41:18 -07:00
node . size_ratio = 1.0 ;
2023-04-16 21:56:19 -07:00
old_parent - > recalcSizePosRecursive ( ) ;
target_group - > recalcSizePosRecursive ( ) ;
2023-04-19 02:07:47 -07:00
auto * target_parent = target_group - > parent ;
2023-04-23 21:02:51 -07:00
while ( target_parent ! = nullptr & & Hy3Node : : swallowGroups ( target_parent ) ) {
2023-04-19 02:07:47 -07:00
target_parent = target_parent - > parent ;
}
2023-04-22 04:14:36 -07:00
auto * focusnode = & node ;
while ( focusnode - > parent ! = nullptr ) {
focusnode - > parent - > data . as_group . lastFocusedChild = focusnode ;
focusnode = focusnode - > parent ;
}
2023-04-19 02:07:47 -07:00
if ( target_parent ! = target_group & & target_parent ! = nullptr )
target_parent - > recalcSizePosRecursive ( ) ;
2023-04-13 14:12:48 -07:00
}
return nullptr ;
}
2023-04-19 01:58:22 -07:00
std : : string Hy3Node : : debugNode ( ) {
std : : stringstream buf ;
std : : string addr = " 0x " + std : : to_string ( ( size_t ) this ) ;
switch ( this - > data . type ) {
case Hy3NodeData : : Window :
buf < < " window( " ;
buf < < std : : hex < < this ;
buf < < " ) [hypr " ;
buf < < this - > data . as_window ;
buf < < " ] " ;
break ;
case Hy3NodeData : : Group :
buf < < " group( " ;
buf < < std : : hex < < this ;
buf < < " ) [ " ;
switch ( this - > data . as_group . layout ) {
case Hy3GroupLayout : : SplitH :
buf < < " splith " ;
break ;
case Hy3GroupLayout : : SplitV :
buf < < " splitv " ;
break ;
case Hy3GroupLayout : : Tabbed :
buf < < " tabs " ;
break ;
}
buf < < " ] " ;
for ( auto * child : this - > data . as_group . children ) {
buf < < " \n |- " ;
// this is terrible
for ( char c : child - > debugNode ( ) ) {
buf < < c ;
if ( c = = ' \n ' ) buf < < " " ;
}
}
break ;
}
return buf . str ( ) ;
}