2022-03-20 16:51:14 +01:00
# include "HyprCtl.hpp"
2024-06-11 19:49:54 +02:00
# include <format>
2022-03-21 18:29:41 +01:00
# include <netinet/in.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/socket.h>
2022-03-20 16:51:14 +01:00
# include <sys/stat.h>
2022-03-21 18:29:41 +01:00
# include <sys/types.h>
2024-01-01 17:53:00 +01:00
# include <sys/utsname.h>
2022-05-24 19:42:43 +02:00
# include <sys/un.h>
2022-03-20 16:51:14 +01:00
# include <unistd.h>
2024-06-18 21:38:33 +02:00
# include <sys/poll.h>
2024-07-21 13:09:54 +02:00
# include <filesystem>
# include <ranges>
2022-03-20 16:51:14 +01:00
2023-01-31 00:03:23 +00:00
# include <sstream>
2022-03-20 16:51:14 +01:00
# include <string>
2024-02-18 15:00:34 +00:00
# include <typeindex>
2024-05-29 05:37:24 +08:00
# include <numeric>
2022-03-20 16:51:14 +01:00
2024-06-11 17:17:45 +02:00
# include <hyprutils/string/String.hpp>
using namespace Hyprutils : : String ;
2024-07-21 13:09:54 +02:00
# include <aquamarine/input/Input.hpp>
2024-06-11 17:17:45 +02:00
2024-04-09 18:14:53 +03:00
# include "../config/ConfigDataValues.hpp"
2024-03-03 18:39:20 +00:00
# include "../config/ConfigValue.hpp"
2024-03-09 16:52:59 +00:00
# include "../managers/CursorManager.hpp"
2024-03-20 21:55:13 -04:00
# include "../hyprerror/HyprError.hpp"
2024-05-03 22:34:10 +01:00
# include "../devices/IPointer.hpp"
# include "../devices/IKeyboard.hpp"
# include "../devices/ITouch.hpp"
2024-05-06 02:15:26 +01:00
# include "../devices/Tablet.hpp"
2024-07-30 16:33:56 -05:00
# include "../protocols/GlobalShortcuts.hpp"
2024-06-14 13:11:40 +03:00
# include "debug/RollingLogFollow.hpp"
2024-05-25 20:46:07 +00:00
# include "config/ConfigManager.hpp"
2024-06-11 19:49:54 +02:00
# include "helpers/MiscFunctions.hpp"
2024-03-03 18:39:20 +00:00
2023-05-24 08:46:56 -07:00
static void trimTrailingComma ( std : : string & str ) {
if ( ! str . empty ( ) & & str . back ( ) = = ' , ' )
str . pop_back ( ) ;
}
2024-03-05 13:55:33 +00:00
static std : : string formatToString ( uint32_t drmFormat ) {
switch ( drmFormat ) {
case DRM_FORMAT_XRGB2101010 : return " XRGB2101010 " ;
case DRM_FORMAT_XBGR2101010 : return " XBGR2101010 " ;
case DRM_FORMAT_XRGB8888 : return " XRGB8888 " ;
case DRM_FORMAT_XBGR8888 : return " XBGR8888 " ;
default : break ;
}
return " Invalid " ;
}
static std : : string availableModesForOutput ( CMonitor * pMonitor , eHyprCtlOutputFormat format ) {
std : : string result ;
2024-08-26 20:24:30 +02:00
for ( auto const & m : pMonitor - > output - > modes ) {
2024-07-21 13:09:54 +02:00
if ( format = = FORMAT_NORMAL )
result + = std : : format ( " {}x{}@{:.2f}Hz " , m - > pixelSize . x , m - > pixelSize . y , m - > refreshRate / 1000.0 ) ;
else
result + = std : : format ( " \" {}x{}@{:.2f}Hz \" , " , m - > pixelSize . x , m - > pixelSize . y , m - > refreshRate / 1000.0 ) ;
2024-03-05 13:55:33 +00:00
}
2024-07-21 13:09:54 +02:00
trimTrailingComma ( result ) ;
2024-03-05 13:55:33 +00:00
return result ;
}
2024-07-07 17:52:56 +02:00
std : : string CHyprCtl : : getMonitorData ( Hyprutils : : Memory : : CSharedPointer < CMonitor > m , eHyprCtlOutputFormat format ) {
std : : string result ;
2024-08-08 21:01:50 +02:00
if ( ! m - > output | | m - > ID = = - 1 )
2024-07-07 17:52:56 +02:00
return " " ;
2023-03-16 00:18:39 +00:00
2024-07-21 13:09:54 +02:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
result + = std : : format (
R " #({{
2023-09-06 12:51:36 +02:00
" id " : { } ,
" name " : " {} " ,
" description " : " {} " ,
" make " : " {} " ,
" model " : " {} " ,
" serial " : " {} " ,
" width " : { } ,
" height " : { } ,
" refreshRate " : { : .5f } ,
" x " : { } ,
" y " : { } ,
" activeWorkspace " : { {
" id " : { } ,
" name " : " {} "
} } ,
" specialWorkspace " : { {
" id " : { } ,
" name " : " {} "
} } ,
" reserved " : [ { } , { } , { } , { } ] ,
" scale " : { : .2f } ,
" transform " : { } ,
" focused " : { } ,
" dpmsStatus " : { } ,
2023-09-30 13:08:55 +01:00
" vrr " : { } ,
2024-03-05 13:55:33 +00:00
" activelyTearing " : { } ,
2024-04-10 09:50:00 +01:00
" disabled " : { } ,
2024-03-05 13:55:33 +00:00
" currentFormat " : " {} " ,
" availableModes " : [ { } ]
2023-09-06 12:51:36 +02:00
} } , ) # " ,
2024-07-21 13:09:54 +02:00
m - > ID , escapeJSONStrings ( m - > szName ) , escapeJSONStrings ( m - > szShortDescription ) , escapeJSONStrings ( m - > output - > make ) , escapeJSONStrings ( m - > output - > model ) ,
escapeJSONStrings ( m - > output - > serial ) , ( int ) m - > vecPixelSize . x , ( int ) m - > vecPixelSize . y , m - > refreshRate , ( int ) m - > vecPosition . x , ( int ) m - > vecPosition . y ,
m - > activeWorkspaceID ( ) , ( ! m - > activeWorkspace ? " " : escapeJSONStrings ( m - > activeWorkspace - > m_szName ) ) , m - > activeSpecialWorkspaceID ( ) ,
escapeJSONStrings ( m - > activeSpecialWorkspace ? m - > activeSpecialWorkspace - > m_szName : " " ) , ( int ) m - > vecReservedTopLeft . x , ( int ) m - > vecReservedTopLeft . y ,
( int ) m - > vecReservedBottomRight . x , ( int ) m - > vecReservedBottomRight . y , m - > scale , ( int ) m - > transform , ( m = = g_pCompositor - > m_pLastMonitor ? " true " : " false " ) ,
( m - > dpmsStatus ? " true " : " false " ) , ( m - > output - > state - > state ( ) . adaptiveSync ? " true " : " false " ) , ( m - > tearingState . activelyTearing ? " true " : " false " ) ,
( m - > m_bEnabled ? " false " : " true " ) , formatToString ( m - > output - > state - > state ( ) . drmFormat ) , availableModesForOutput ( m . get ( ) , format ) ) ;
} else {
result + = std : : format ( " Monitor {} (ID {}): \n \t {}x{}@{:.5f} at {}x{} \n \t description: {} \n \t make: {} \n \t model: {} \n \t serial: {} \n \t active workspace: {} ({}) \n \t "
" special workspace: {} ({}) \n \t reserved: {} {} {} {} \n \t scale: {:.2f} \n \t transform: {} \n \t focused: {} \n \t "
" dpmsStatus: {} \n \t vrr: {} \n \t activelyTearing: {} \n \t disabled: {} \n \t currentFormat: {} \n \t availableModes: {} \n \n " ,
m - > szName , m - > ID , ( int ) m - > vecPixelSize . x , ( int ) m - > vecPixelSize . y , m - > refreshRate , ( int ) m - > vecPosition . x , ( int ) m - > vecPosition . y , m - > szShortDescription ,
m - > output - > make , m - > output - > model , m - > output - > serial , m - > activeWorkspaceID ( ) , ( ! m - > activeWorkspace ? " " : m - > activeWorkspace - > m_szName ) ,
m - > activeSpecialWorkspaceID ( ) , ( m - > activeSpecialWorkspace ? m - > activeSpecialWorkspace - > m_szName : " " ) , ( int ) m - > vecReservedTopLeft . x ,
( int ) m - > vecReservedTopLeft . y , ( int ) m - > vecReservedBottomRight . x , ( int ) m - > vecReservedBottomRight . y , m - > scale , ( int ) m - > transform ,
( m = = g_pCompositor - > m_pLastMonitor ? " yes " : " no " ) , ( int ) m - > dpmsStatus , m - > output - > state - > state ( ) . adaptiveSync , m - > tearingState . activelyTearing ,
! m - > m_bEnabled , formatToString ( m - > output - > state - > state ( ) . drmFormat ) , availableModesForOutput ( m . get ( ) , format ) ) ;
}
2024-07-07 17:52:56 +02:00
return result ;
}
std : : string monitorsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
CVarList vars ( request , 0 , ' ' ) ;
auto allMonitors = false ;
if ( vars . size ( ) > 2 )
return " too many args " ;
if ( vars . size ( ) = = 2 & & vars [ 1 ] = = " all " )
allMonitors = true ;
std : : string result = " " ;
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
result + = " [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & m : allMonitors ? g_pCompositor - > m_vRealMonitors : g_pCompositor - > m_vMonitors ) {
2024-07-07 17:52:56 +02:00
result + = CHyprCtl : : getMonitorData ( m , format ) ;
2022-07-12 11:57:33 -06:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " ] " ;
} else {
2024-08-26 17:25:39 +02:00
for ( auto const & m : allMonitors ? g_pCompositor - > m_vRealMonitors : g_pCompositor - > m_vMonitors ) {
2024-08-08 21:01:50 +02:00
if ( ! m - > output | | m - > ID = = - 1 )
2023-03-16 00:18:39 +00:00
continue ;
2024-08-17 19:27:11 +02:00
result + = std : : format (
" Monitor {} (ID {}): \n \t {}x{}@{:.5f} at {}x{} \n \t description: {} \n \t make: {} \n \t model: {} \n \t serial: {} \n \t active workspace: {} ({}) \n \t "
" special workspace: {} ({}) \n \t reserved: {} {} {} {} \n \t scale: {:.2f} \n \t transform: {} \n \t focused: {} \n \t "
" dpmsStatus: {} \n \t vrr: {} \n \t activelyTearing: {} \n \t disabled: {} \n \t currentFormat: A {} H {} \n \t availableModes: {} \n \n " ,
m - > szName , m - > ID , ( int ) m - > vecPixelSize . x , ( int ) m - > vecPixelSize . y , m - > refreshRate , ( int ) m - > vecPosition . x , ( int ) m - > vecPosition . y , m - > szShortDescription ,
m - > output - > make , m - > output - > model , m - > output - > serial , m - > activeWorkspaceID ( ) , ( ! m - > activeWorkspace ? " " : m - > activeWorkspace - > m_szName ) ,
m - > activeSpecialWorkspaceID ( ) , ( m - > activeSpecialWorkspace ? m - > activeSpecialWorkspace - > m_szName : " " ) , ( int ) m - > vecReservedTopLeft . x , ( int ) m - > vecReservedTopLeft . y ,
( int ) m - > vecReservedBottomRight . x , ( int ) m - > vecReservedBottomRight . y , m - > scale , ( int ) m - > transform , ( m = = g_pCompositor - > m_pLastMonitor ? " yes " : " no " ) ,
( int ) m - > dpmsStatus , ( int ) ( m - > output - > state ? m - > output - > state - > state ( ) . adaptiveSync : false ) , m - > tearingState . activelyTearing , ! m - > m_bEnabled ,
formatToString ( m - > output - > state - > state ( ) . drmFormat ) , formatToString ( m - > drmFormat ) , availableModesForOutput ( m . get ( ) , format ) ) ;
2022-07-12 11:57:33 -06:00
}
2022-03-20 16:51:14 +01:00
}
return result ;
}
2024-05-29 05:37:24 +08:00
static std : : string getTagsData ( PHLWINDOW w , eHyprCtlOutputFormat format ) {
const auto tags = w - > m_tags . getTags ( ) ;
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON )
return std : : accumulate ( tags . begin ( ) , tags . end ( ) , std : : string ( ) ,
[ ] ( const std : : string & a , const std : : string & b ) { return a . empty ( ) ? std : : format ( " \" {} \" " , b ) : std : : format ( " {}, \" {} \" " , a , b ) ; } ) ;
else
return std : : accumulate ( tags . begin ( ) , tags . end ( ) , std : : string ( ) , [ ] ( const std : : string & a , const std : : string & b ) { return a . empty ( ) ? b : a + " , " + b ; } ) ;
}
2024-04-27 12:43:12 +01:00
static std : : string getGroupedData ( PHLWINDOW w , eHyprCtlOutputFormat format ) {
2024-02-05 01:56:38 +00:00
const bool isJson = format = = eHyprCtlOutputFormat : : FORMAT_JSON ;
2024-04-27 12:43:12 +01:00
if ( w - > m_sGroupData . pNextWindow . expired ( ) )
2022-12-04 13:03:29 -08:00
return isJson ? " " : " 0 " ;
std : : ostringstream result ;
2024-04-27 12:43:12 +01:00
PHLWINDOW head = w - > getGroupHead ( ) ;
PHLWINDOW curr = head ;
2023-11-09 17:05:05 +01:00
while ( true ) {
2023-09-20 07:26:20 +00:00
if ( isJson )
2024-04-27 12:43:12 +01:00
result < < std : : format ( " \" 0x{:x} \" " , ( uintptr_t ) curr . get ( ) ) ;
2023-09-20 07:26:20 +00:00
else
2024-04-27 12:43:12 +01:00
result < < std : : format ( " {:x} " , ( uintptr_t ) curr . get ( ) ) ;
curr = curr - > m_sGroupData . pNextWindow . lock ( ) ;
2023-11-09 17:05:05 +01:00
// We've wrapped around to the start, break out without trailing comma
if ( curr = = head )
break ;
result < < ( isJson ? " , " : " , " ) ;
2022-12-04 13:03:29 -08:00
}
return result . str ( ) ;
}
2024-07-07 17:52:56 +02:00
std : : string CHyprCtl : : getWindowData ( PHLWINDOW w , eHyprCtlOutputFormat format ) {
2024-04-27 12:43:12 +01:00
auto getFocusHistoryID = [ ] ( PHLWINDOW wnd ) - > int {
2023-10-28 17:22:31 +01:00
for ( size_t i = 0 ; i < g_pCompositor - > m_vWindowFocusHistory . size ( ) ; + + i ) {
2024-04-27 12:43:12 +01:00
if ( g_pCompositor - > m_vWindowFocusHistory [ i ] . lock ( ) = = wnd )
2023-10-28 17:22:31 +01:00
return i ;
}
return - 1 ;
} ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-09-20 07:26:20 +00:00
return std : : format (
2023-09-06 12:51:36 +02:00
R " #({{
" address " : " 0x{:x} " ,
" mapped " : { } ,
" hidden " : { } ,
" at " : [ { } , { } ] ,
" size " : [ { } , { } ] ,
" workspace " : { {
" id " : { } ,
" name " : " {} "
} } ,
" floating " : { } ,
2024-06-19 23:19:18 +02:00
" pseudo " : { } ,
2023-09-06 12:51:36 +02:00
" monitor " : { } ,
" class " : " {} " ,
" title " : " {} " ,
" initialClass " : " {} " ,
" initialTitle " : " {} " ,
" pid " : { } ,
" xwayland " : { } ,
" pinned " : { } ,
" fullscreen " : { } ,
2024-07-31 17:55:52 +00:00
" fullscreenClient " : { } ,
2023-09-06 12:51:36 +02:00
" grouped " : [ { } ] ,
2024-05-29 05:37:24 +08:00
" tags " : [ { } ] ,
2023-10-28 17:22:31 +01:00
" swallowing " : " 0x{:x} " ,
" focusHistoryID " : { }
2023-09-06 12:51:36 +02:00
} } , ) # " ,
2024-04-27 12:43:12 +01:00
( uintptr_t ) w . get ( ) , ( w - > m_bIsMapped ? " true " : " false " ) , ( w - > isHidden ( ) ? " true " : " false " ) , ( int ) w - > m_vRealPosition . goal ( ) . x , ( int ) w - > m_vRealPosition . goal ( ) . y ,
2024-04-02 20:32:39 +01:00
( int ) w - > m_vRealSize . goal ( ) . x , ( int ) w - > m_vRealSize . goal ( ) . y , w - > m_pWorkspace ? w - > workspaceID ( ) : WORKSPACE_INVALID ,
2024-06-19 23:19:18 +02:00
escapeJSONStrings ( ! w - > m_pWorkspace ? " " : w - > m_pWorkspace - > m_szName ) , ( ( int ) w - > m_bIsFloating = = 1 ? " true " : " false " ) , ( w - > m_bIsPseudotiled ? " true " : " false " ) ,
( int64_t ) w - > m_iMonitorID , escapeJSONStrings ( w - > m_szClass ) , escapeJSONStrings ( w - > m_szTitle ) , escapeJSONStrings ( w - > m_szInitialClass ) ,
escapeJSONStrings ( w - > m_szInitialTitle ) , w - > getPID ( ) , ( ( int ) w - > m_bIsX11 = = 1 ? " true " : " false " ) , ( w - > m_bPinned ? " true " : " false " ) ,
2024-07-31 17:55:52 +00:00
( uint8_t ) w - > m_sFullscreenState . internal , ( uint8_t ) w - > m_sFullscreenState . client , getGroupedData ( w , format ) , getTagsData ( w , format ) ,
( uintptr_t ) w - > m_pSwallowed . lock ( ) . get ( ) , getFocusHistoryID ( w ) ) ;
2022-11-13 01:39:21 +01:00
} else {
2024-06-19 23:19:18 +02:00
return std : : format (
" Window {:x} -> {}: \n \t mapped: {} \n \t hidden: {} \n \t at: {},{} \n \t size: {},{} \n \t workspace: {} ({}) \n \t floating: {} \n \t pseudo: {} \n \t monitor: {} \n \t class: {} \n \t title: "
" {} \n \t initialClass: {} \n \t initialTitle: {} \n \t pid: "
" {} \n \t xwayland: {} \n \t pinned: "
2024-07-31 17:55:52 +00:00
" {} \n \t fullscreen: {} \n \t fullscreenClient: {} \n \t grouped: {} \n \t tags: {} \n \t swallowing: {:x} \n \t focusHistoryID: {} \n \n " ,
2024-06-19 23:19:18 +02:00
( uintptr_t ) w . get ( ) , w - > m_szTitle , ( int ) w - > m_bIsMapped , ( int ) w - > isHidden ( ) , ( int ) w - > m_vRealPosition . goal ( ) . x , ( int ) w - > m_vRealPosition . goal ( ) . y ,
( int ) w - > m_vRealSize . goal ( ) . x , ( int ) w - > m_vRealSize . goal ( ) . y , w - > m_pWorkspace ? w - > workspaceID ( ) : WORKSPACE_INVALID , ( ! w - > m_pWorkspace ? " " : w - > m_pWorkspace - > m_szName ) ,
( int ) w - > m_bIsFloating , ( int ) w - > m_bIsPseudotiled , ( int64_t ) w - > m_iMonitorID , w - > m_szClass , w - > m_szTitle , w - > m_szInitialClass , w - > m_szInitialTitle , w - > getPID ( ) ,
2024-07-31 17:55:52 +00:00
( int ) w - > m_bIsX11 , ( int ) w - > m_bPinned , ( uint8_t ) w - > m_sFullscreenState . internal , ( uint8_t ) w - > m_sFullscreenState . client , getGroupedData ( w , format ) , getTagsData ( w , format ) ,
( uintptr_t ) w - > m_pSwallowed . lock ( ) . get ( ) , getFocusHistoryID ( w ) ) ;
2022-11-13 01:39:21 +01:00
}
}
2024-02-05 01:56:38 +00:00
std : : string clientsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-11-13 01:39:21 +01:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2022-11-13 01:39:21 +01:00
result + = " [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-03-08 17:47:12 +00:00
if ( ! w - > m_bIsMapped & & ! g_pHyprCtl - > m_sCurrentRequestParams . all )
continue ;
2024-07-07 17:52:56 +02:00
result + = CHyprCtl : : getWindowData ( w , format ) ;
2022-07-12 11:57:33 -06:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " ] " ;
} else {
2024-08-26 17:25:39 +02:00
for ( auto const & w : g_pCompositor - > m_vWindows ) {
2024-03-08 17:47:12 +00:00
if ( ! w - > m_bIsMapped & & ! g_pHyprCtl - > m_sCurrentRequestParams . all )
continue ;
2024-07-07 17:52:56 +02:00
result + = CHyprCtl : : getWindowData ( w , format ) ;
2022-06-27 13:17:11 +02:00
}
2022-03-20 16:51:14 +01:00
}
return result ;
}
2024-07-07 17:52:56 +02:00
std : : string CHyprCtl : : getWorkspaceData ( PHLWORKSPACE w , eHyprCtlOutputFormat format ) {
2023-05-02 06:51:52 -07:00
const auto PLASTW = w - > getLastFocusedWindow ( ) ;
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( w - > m_iMonitorID ) ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-09-20 07:26:20 +00:00
return std : : format ( R " #({{
2023-09-06 12:51:36 +02:00
" id " : { } ,
" name " : " {} " ,
" monitor " : " {} " ,
2023-10-24 01:03:40 +01:00
" monitorID " : { } ,
2023-09-06 12:51:36 +02:00
" windows " : { } ,
" hasfullscreen " : { } ,
" lastwindow " : " 0x{:x} " ,
" lastwindowtitle " : " {} "
} } ) # " ,
2023-10-24 01:03:40 +01:00
w - > m_iID , escapeJSONStrings ( w - > m_szName ) , escapeJSONStrings ( PMONITOR ? PMONITOR - > szName : " ? " ) ,
2023-11-01 18:53:36 +00:00
escapeJSONStrings ( PMONITOR ? std : : to_string ( PMONITOR - > ID ) : " null " ) , g_pCompositor - > getWindowsOnWorkspace ( w - > m_iID ) ,
2024-04-27 12:43:12 +01:00
( ( int ) w - > m_bHasFullscreenWindow = = 1 ? " true " : " false " ) , ( uintptr_t ) PLASTW . get ( ) , PLASTW ? escapeJSONStrings ( PLASTW - > m_szTitle ) : " " ) ;
2023-05-02 06:51:52 -07:00
} else {
2023-10-24 01:03:40 +01:00
return std : : format ( " workspace ID {} ({}) on monitor {}: \n \t monitorID: {} \n \t windows: {} \n \t hasfullscreen: {} \n \t lastwindow: 0x{:x} \n \t lastwindowtitle: {} \n \n " , w - > m_iID ,
w - > m_szName , PMONITOR ? PMONITOR - > szName : " ? " , PMONITOR ? std : : to_string ( PMONITOR - > ID ) : " null " , g_pCompositor - > getWindowsOnWorkspace ( w - > m_iID ) ,
2024-04-27 12:43:12 +01:00
( int ) w - > m_bHasFullscreenWindow , ( uintptr_t ) PLASTW . get ( ) , PLASTW ? PLASTW - > m_szTitle : " " ) ;
2023-05-02 06:51:52 -07:00
}
}
2024-02-05 01:56:38 +00:00
static std : : string getWorkspaceRuleData ( const SWorkspaceRule & r , eHyprCtlOutputFormat format ) {
2023-10-21 03:28:34 +02:00
const auto boolToString = [ ] ( const bool b ) - > std : : string { return b ? " true " : " false " ; } ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-10-21 03:28:34 +02:00
const std : : string monitor = r . monitor . empty ( ) ? " " : std : : format ( " , \n \" monitor \" : \" {} \" " , escapeJSONStrings ( r . monitor ) ) ;
const std : : string default_ = ( bool ) ( r . isDefault ) ? std : : format ( " , \n \" default \" : {} " , boolToString ( r . isDefault ) ) : " " ;
const std : : string persistent = ( bool ) ( r . isPersistent ) ? std : : format ( " , \n \" persistent \" : {} " , boolToString ( r . isPersistent ) ) : " " ;
2024-02-23 21:25:04 +00:00
const std : : string gapsIn = ( bool ) ( r . gapsIn ) ?
std : : format ( " , \n \" gapsIn \" : [{}, {}, {}, {}] " , r . gapsIn . value ( ) . top , r . gapsIn . value ( ) . right , r . gapsIn . value ( ) . bottom , r . gapsIn . value ( ) . left ) :
" " ;
2024-02-21 12:07:39 +01:00
const std : : string gapsOut = ( bool ) ( r . gapsOut ) ?
2024-02-23 21:25:04 +00:00
std : : format ( " , \n \" gapsOut \" : [{}, {}, {}, {}] " , r . gapsOut . value ( ) . top , r . gapsOut . value ( ) . right , r . gapsOut . value ( ) . bottom , r . gapsOut . value ( ) . left ) :
2024-02-21 12:07:39 +01:00
" " ;
2023-10-21 03:28:34 +02:00
const std : : string borderSize = ( bool ) ( r . borderSize ) ? std : : format ( " , \n \" borderSize \" : {} " , r . borderSize . value ( ) ) : " " ;
2024-07-11 14:10:42 +00:00
const std : : string border = ( bool ) ( r . noBorder ) ? std : : format ( " , \n \" border \" : {} " , boolToString ( ! r . noBorder . value ( ) ) ) : " " ;
const std : : string rounding = ( bool ) ( r . noRounding ) ? std : : format ( " , \n \" rounding \" : {} " , boolToString ( ! r . noRounding . value ( ) ) ) : " " ;
2023-10-21 03:28:34 +02:00
const std : : string decorate = ( bool ) ( r . decorate ) ? std : : format ( " , \n \" decorate \" : {} " , boolToString ( r . decorate . value ( ) ) ) : " " ;
2024-07-11 14:10:42 +00:00
const std : : string shadow = ( bool ) ( r . noShadow ) ? std : : format ( " , \n \" shadow \" : {} " , boolToString ( ! r . noShadow . value ( ) ) ) : " " ;
2023-10-21 03:28:34 +02:00
std : : string result = std : : format ( R " #({{
" workspaceString " : " {} " { } { } { } { } { } { } { } { }
} } ) # " ,
2023-11-21 13:43:38 -05:00
escapeJSONStrings ( r . workspaceString ) , monitor , default_ , persistent , gapsIn , gapsOut , borderSize , border , rounding , decorate , shadow ) ;
2023-10-21 03:28:34 +02:00
return result ;
} else {
const std : : string monitor = std : : format ( " \t monitor: {} \n " , r . monitor . empty ( ) ? " <unset> " : escapeJSONStrings ( r . monitor ) ) ;
const std : : string default_ = std : : format ( " \t default: {} \n " , ( bool ) ( r . isDefault ) ? boolToString ( r . isDefault ) : " <unset> " ) ;
const std : : string persistent = std : : format ( " \t persistent: {} \n " , ( bool ) ( r . isPersistent ) ? boolToString ( r . isPersistent ) : " <unset> " ) ;
2024-02-21 12:07:39 +01:00
const std : : string gapsIn = ( bool ) ( r . gapsIn ) ? std : : format ( " \t gapsIn: {} {} {} {} \n " , std : : to_string ( r . gapsIn . value ( ) . top ) , std : : to_string ( r . gapsIn . value ( ) . right ) ,
std : : to_string ( r . gapsIn . value ( ) . bottom ) , std : : to_string ( r . gapsIn . value ( ) . left ) ) :
std : : format ( " \t gapsIn: <unset> \n " ) ;
const std : : string gapsOut = ( bool ) ( r . gapsOut ) ? std : : format ( " \t gapsOut: {} {} {} {} \n " , std : : to_string ( r . gapsOut . value ( ) . top ) , std : : to_string ( r . gapsOut . value ( ) . right ) ,
std : : to_string ( r . gapsOut . value ( ) . bottom ) , std : : to_string ( r . gapsOut . value ( ) . left ) ) :
std : : format ( " \t gapsOut: <unset> \n " ) ;
2023-10-21 03:28:34 +02:00
const std : : string borderSize = std : : format ( " \t borderSize: {} \n " , ( bool ) ( r . borderSize ) ? std : : to_string ( r . borderSize . value ( ) ) : " <unset> " ) ;
2024-07-11 14:10:42 +00:00
const std : : string border = std : : format ( " \t border: {} \n " , ( bool ) ( r . noBorder ) ? boolToString ( ! r . noBorder . value ( ) ) : " <unset> " ) ;
const std : : string rounding = std : : format ( " \t rounding: {} \n " , ( bool ) ( r . noRounding ) ? boolToString ( ! r . noRounding . value ( ) ) : " <unset> " ) ;
2023-10-21 03:28:34 +02:00
const std : : string decorate = std : : format ( " \t decorate: {} \n " , ( bool ) ( r . decorate ) ? boolToString ( r . decorate . value ( ) ) : " <unset> " ) ;
2024-07-11 14:10:42 +00:00
const std : : string shadow = std : : format ( " \t shadow: {} \n " , ( bool ) ( r . noShadow ) ? boolToString ( ! r . noShadow . value ( ) ) : " <unset> " ) ;
2023-10-21 03:28:34 +02:00
std : : string result = std : : format ( " Workspace rule {}: \n {}{}{}{}{}{}{}{}{}{} \n " , escapeJSONStrings ( r . workspaceString ) , monitor , default_ , persistent , gapsIn , gapsOut ,
2023-11-21 13:43:38 -05:00
borderSize , border , rounding , decorate , shadow ) ;
2023-10-21 03:28:34 +02:00
return result ;
}
}
2024-02-05 01:56:38 +00:00
std : : string activeWorkspaceRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-09-25 15:00:19 +01:00
if ( ! g_pCompositor - > m_pLastMonitor )
return " unsafe state " ;
2023-05-02 06:51:52 -07:00
std : : string result = " " ;
2024-04-02 20:32:39 +01:00
auto w = g_pCompositor - > m_pLastMonitor - > activeWorkspace ;
2023-09-25 15:00:19 +01:00
2024-04-02 20:32:39 +01:00
if ( ! valid ( w ) )
2023-09-25 15:00:19 +01:00
return " internal error " ;
2024-07-07 17:52:56 +02:00
return CHyprCtl : : getWorkspaceData ( w , format ) ;
2023-05-02 06:51:52 -07:00
}
2024-02-05 01:56:38 +00:00
std : : string workspacesRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-05-02 06:51:52 -07:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-05-02 06:51:52 -07:00
result + = " [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & w : g_pCompositor - > m_vWorkspaces ) {
2024-07-07 17:52:56 +02:00
result + = CHyprCtl : : getWorkspaceData ( w , format ) ;
2023-05-02 06:51:52 -07:00
result + = " , " ;
2022-07-12 11:57:33 -06:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " ] " ;
} else {
2024-08-26 17:25:39 +02:00
for ( auto const & w : g_pCompositor - > m_vWorkspaces ) {
2024-07-07 17:52:56 +02:00
result + = CHyprCtl : : getWorkspaceData ( w , format ) ;
2022-07-12 11:57:33 -06:00
}
2022-03-20 16:51:14 +01:00
}
2023-05-02 06:51:52 -07:00
2022-03-20 16:51:14 +01:00
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string workspaceRulesRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-10-21 03:28:34 +02:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-10-21 03:28:34 +02:00
result + = " [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & r : g_pConfigManager - > getAllWorkspaceRules ( ) ) {
2023-10-21 03:28:34 +02:00
result + = getWorkspaceRuleData ( r , format ) ;
result + = " , " ;
}
trimTrailingComma ( result ) ;
result + = " ] " ;
} else {
2024-08-26 17:25:39 +02:00
for ( auto const & r : g_pConfigManager - > getAllWorkspaceRules ( ) ) {
2023-10-21 03:28:34 +02:00
result + = getWorkspaceRuleData ( r , format ) ;
}
}
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string activeWindowRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2024-04-27 12:43:12 +01:00
const auto PWINDOW = g_pCompositor - > m_pLastWindow . lock ( ) ;
2022-03-22 16:54:45 +01:00
2024-04-27 12:43:12 +01:00
if ( ! validMapped ( PWINDOW ) )
2024-02-05 01:56:38 +00:00
return format = = eHyprCtlOutputFormat : : FORMAT_JSON ? " {} " : " Invalid " ;
2022-11-13 11:12:04 +00:00
2024-07-07 17:52:56 +02:00
auto result = CHyprCtl : : getWindowData ( PWINDOW , format ) ;
2022-12-16 17:17:31 +00:00
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON )
2022-11-13 11:12:04 +00:00
result . pop_back ( ) ;
return result ;
2022-03-22 16:54:45 +01:00
}
2024-02-05 01:56:38 +00:00
std : : string layersRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-03-22 16:54:45 +01:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2022-07-12 11:57:33 -06:00
result + = " { \n " ;
2024-08-26 17:25:39 +02:00
for ( auto const & mon : g_pCompositor - > m_vMonitors ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( " { } " : {{
" levels " : { {
2022-07-12 11:57:33 -06:00
) # " ,
2023-09-06 21:45:37 +02:00
escapeJSONStrings ( mon - > szName ) ) ;
2022-07-12 11:57:33 -06:00
int layerLevel = 0 ;
2024-08-26 20:24:30 +02:00
for ( auto const & level : mon - > m_aLayerSurfaceLayers ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2022-12-16 17:17:31 +00:00
R " #(
2023-09-06 12:51:36 +02:00
" {} " : [
2022-07-12 11:57:33 -06:00
) # " ,
2022-12-16 17:17:31 +00:00
layerLevel ) ;
2024-08-26 20:24:30 +02:00
for ( auto const & layer : level ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" x " : { } ,
" y " : { } ,
" w " : { } ,
" h " : { } ,
" namespace " : " {} "
} } , ) # " ,
2023-09-06 21:45:37 +02:00
( uintptr_t ) layer . get ( ) , layer - > geometry . x , layer - > geometry . y , layer - > geometry . width , layer - > geometry . height , escapeJSONStrings ( layer - > szNamespace ) ) ;
2022-07-12 11:57:33 -06:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
if ( level . size ( ) > 0 )
result + = " \n " ;
result + = " ], " ;
layerLevel + + ;
2022-03-22 16:54:45 +01:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " \n } \n }, " ;
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " \n } \n " ;
2022-09-25 20:07:48 +02:00
2022-07-12 11:57:33 -06:00
} else {
2024-08-26 20:24:30 +02:00
for ( auto const & mon : g_pCompositor - > m_vMonitors ) {
2023-09-20 07:26:20 +00:00
result + = std : : format ( " Monitor {}: \n " , mon - > szName ) ;
2023-01-09 21:26:07 +01:00
int layerLevel = 0 ;
static const std : : array < std : : string , 4 > levelNames = { " background " , " bottom " , " top " , " overlay " } ;
2024-08-26 20:24:30 +02:00
for ( auto const & level : mon - > m_aLayerSurfaceLayers ) {
2023-09-20 07:26:20 +00:00
result + = std : : format ( " \t Layer level {} ({}): \n " , layerLevel , levelNames [ layerLevel ] ) ;
2022-07-12 11:57:33 -06:00
2024-08-26 20:24:30 +02:00
for ( auto const & layer : level ) {
2023-09-20 07:26:20 +00:00
result + = std : : format ( " \t \t Layer {:x}: xywh: {} {} {} {}, namespace: {} \n " , ( uintptr_t ) layer . get ( ) , layer - > geometry . x , layer - > geometry . y , layer - > geometry . width ,
layer - > geometry . height , layer - > szNamespace ) ;
2022-07-12 11:57:33 -06:00
}
layerLevel + + ;
}
result + = " \n \n " ;
2022-03-22 16:54:45 +01:00
}
}
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string layoutsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-11-21 13:43:38 -05:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-11-21 13:43:38 -05:00
result + = " [ " ;
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pLayoutManager - > getAllLayoutNames ( ) ) {
2023-11-21 13:43:38 -05:00
result + = std : : format (
R " #(
" {} " , ) # " ,
m ) ;
}
trimTrailingComma ( result ) ;
result + = " \n ] \n " ;
} else {
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pLayoutManager - > getAllLayoutNames ( ) ) {
2023-11-21 13:43:38 -05:00
result + = std : : format ( " {} \n " , m ) ;
}
}
return result ;
}
2024-03-20 21:55:13 -04:00
std : : string configErrorsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
std : : string result = " " ;
std : : string currErrors = g_pConfigManager - > getErrors ( ) ;
CVarList errLines ( currErrors , 0 , ' \n ' ) ;
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
result + = " [ " ;
for ( auto line : errLines ) {
result + = std : : format (
R " #(
" {} " , ) # " ,
escapeJSONStrings ( line ) ) ;
}
trimTrailingComma ( result ) ;
result + = " \n ] \n " ;
} else {
for ( auto line : errLines ) {
result + = std : : format ( " {} \n " , line ) ;
}
}
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string devicesRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-06-02 13:59:33 +02:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2022-07-12 11:57:33 -06:00
result + = " { \n " ;
result + = " \" mice \" : [ \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pInputManager - > m_vPointers ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" name " : " {} " ,
" defaultSpeed " : { : .5f }
} } , ) # " ,
2024-05-03 22:34:10 +01:00
( uintptr_t ) m . get ( ) , escapeJSONStrings ( m - > hlName ) ,
2024-07-21 13:09:54 +02:00
m - > aq ( ) & & m - > aq ( ) - > getLibinputHandle ( ) ? libinput_device_config_accel_get_default_speed ( m - > aq ( ) - > getLibinputHandle ( ) ) : 0.f ) ;
2022-07-12 11:57:33 -06:00
}
2022-06-02 13:59:33 +02:00
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " \n ], \n " ;
result + = " \" keyboards \" : [ \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & k : g_pInputManager - > m_vKeyboards ) {
2024-05-03 22:34:10 +01:00
const auto KM = k - > getActiveLayout ( ) ;
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" name " : " {} " ,
" rules " : " {} " ,
" model " : " {} " ,
" layout " : " {} " ,
" variant " : " {} " ,
" options " : " {} " ,
" active_keymap " : " {} " ,
" main " : { }
} } , ) # " ,
2024-05-03 22:34:10 +01:00
( uintptr_t ) k . get ( ) , escapeJSONStrings ( k - > hlName ) , escapeJSONStrings ( k - > currentRules . rules ) , escapeJSONStrings ( k - > currentRules . model ) ,
escapeJSONStrings ( k - > currentRules . layout ) , escapeJSONStrings ( k - > currentRules . variant ) , escapeJSONStrings ( k - > currentRules . options ) , escapeJSONStrings ( KM ) ,
( k - > active ? " true " : " false " ) ) ;
2022-07-12 11:57:33 -06:00
}
2022-06-02 13:59:33 +02:00
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " \n ], \n " ;
2022-06-02 13:59:33 +02:00
2022-07-12 11:57:33 -06:00
result + = " \" tablets \" : [ \n " ;
2022-06-02 13:59:33 +02:00
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTabletPads ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
2022-07-12 11:57:33 -06:00
" type " : " tabletPad " ,
2023-09-06 12:51:36 +02:00
" belongsTo " : { {
" address " : " 0x{:x} " ,
" name " : " {} "
} }
} } , ) # " ,
2024-05-06 02:15:26 +01:00
( uintptr_t ) d . get ( ) , ( uintptr_t ) d - > parent . get ( ) , escapeJSONStrings ( d - > parent ? d - > parent - > hlName : " " ) ) ;
2022-07-12 11:57:33 -06:00
}
2022-06-09 19:25:26 +02:00
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTablets ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" name " : " {} "
} } , ) # " ,
2024-05-06 02:15:26 +01:00
( uintptr_t ) d . get ( ) , escapeJSONStrings ( d - > hlName ) ) ;
2022-07-12 11:57:33 -06:00
}
2022-06-09 19:25:26 +02:00
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTabletTools ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
2022-07-12 11:57:33 -06:00
" type " : " tabletTool " ,
2023-09-06 12:51:36 +02:00
} } , ) # " ,
2024-07-21 13:09:54 +02:00
( uintptr_t ) d . get ( ) ) ;
2022-07-12 11:57:33 -06:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-09-21 14:39:25 +01:00
result + = " \n ], \n " ;
result + = " \" touch \" : [ \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTouches ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" name " : " {} "
} } , ) # " ,
2024-05-03 22:34:10 +01:00
( uintptr_t ) d . get ( ) , escapeJSONStrings ( d - > hlName ) ) ;
2022-09-21 14:39:25 +01:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-10-04 20:07:21 +01:00
result + = " \n ], \n " ;
result + = " \" switches \" : [ \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_lSwitches ) {
2023-09-20 07:26:20 +00:00
result + = std : : format (
2023-09-06 12:51:36 +02:00
R " #( {{
" address " : " 0x{:x} " ,
" name " : " {} "
} } , ) # " ,
2024-07-21 13:09:54 +02:00
( uintptr_t ) & d , escapeJSONStrings ( d . pDevice ? d . pDevice - > getName ( ) : " " ) ) ;
2022-10-04 20:07:21 +01:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-07-12 11:57:33 -06:00
result + = " \n ] \n " ;
2022-06-09 19:25:26 +02:00
2022-07-12 11:57:33 -06:00
result + = " } \n " ;
} else {
result + = " mice: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pInputManager - > m_vPointers ) {
2024-05-03 22:34:10 +01:00
result + = std : : format ( " \t Mouse at {:x}: \n \t \t {} \n \t \t \t default speed: {:.5f} \n " , ( uintptr_t ) m . get ( ) , m - > hlName ,
2024-07-21 13:09:54 +02:00
( m - > aq ( ) & & m - > aq ( ) - > getLibinputHandle ( ) ? libinput_device_config_accel_get_default_speed ( m - > aq ( ) - > getLibinputHandle ( ) ) : 0.f ) ) ;
2022-07-12 11:57:33 -06:00
}
result + = " \n \n Keyboards: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & k : g_pInputManager - > m_vKeyboards ) {
2024-05-03 22:34:10 +01:00
const auto KM = k - > getActiveLayout ( ) ;
2023-09-20 07:26:20 +00:00
result + = std : : format ( " \t Keyboard at {:x}: \n \t \t {} \n \t \t \t rules: r \" {} \" , m \" {} \" , l \" {} \" , v \" {} \" , o \" {} \" \n \t \t \t active keymap: {} \n \t \t \t main: {} \n " ,
2024-05-03 22:34:10 +01:00
( uintptr_t ) k . get ( ) , k - > hlName , k - > currentRules . rules , k - > currentRules . model , k - > currentRules . layout , k - > currentRules . variant ,
k - > currentRules . options , KM , ( k - > active ? " yes " : " no " ) ) ;
2022-07-12 11:57:33 -06:00
}
result + = " \n \n Tablets: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTabletPads ) {
2024-05-06 02:15:26 +01:00
result + = std : : format ( " \t Tablet Pad at {:x} (belongs to {:x} -> {}) \n " , ( uintptr_t ) d . get ( ) , ( uintptr_t ) d - > parent . get ( ) , d - > parent ? d - > parent - > hlName : " " ) ;
2022-07-12 11:57:33 -06:00
}
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTablets ) {
2024-07-21 13:09:54 +02:00
result + = std : : format ( " \t Tablet at {:x}: \n \t \t {} \n \t \t \t size: {}x{}mm \n " , ( uintptr_t ) d . get ( ) , d - > hlName , d - > aq ( ) - > physicalSize . x , d - > aq ( ) - > physicalSize . y ) ;
2022-07-12 11:57:33 -06:00
}
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTabletTools ) {
2024-07-21 13:09:54 +02:00
result + = std : : format ( " \t Tablet Tool at {:x} \n " , ( uintptr_t ) d . get ( ) ) ;
2022-07-12 11:57:33 -06:00
}
2022-09-21 14:39:25 +01:00
result + = " \n \n Touch: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_vTouches ) {
2024-05-03 22:34:10 +01:00
result + = std : : format ( " \t Touch Device at {:x}: \n \t \t {} \n " , ( uintptr_t ) d . get ( ) , d - > hlName ) ;
2022-09-21 14:39:25 +01:00
}
2022-10-04 20:07:21 +01:00
result + = " \n \n Switches: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & d : g_pInputManager - > m_lSwitches ) {
2024-07-21 13:09:54 +02:00
result + = std : : format ( " \t Switch Device at {:x}: \n \t \t {} \n " , ( uintptr_t ) & d , d . pDevice ? d . pDevice - > getName ( ) : " " ) ;
2022-10-04 20:07:21 +01:00
}
2022-06-09 19:25:26 +02:00
}
2022-06-02 13:59:33 +02:00
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string animationsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-01-25 15:16:28 +00:00
std : : string ret = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
2023-01-25 15:16:28 +00:00
ret + = " animations: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & ac : g_pConfigManager - > getAnimationConfig ( ) ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format ( " \n \t name: {} \n \t \t overriden: {} \n \t \t bezier: {} \n \t \t enabled: {} \n \t \t speed: {:.2f} \n \t \t style: {} \n " , ac . first , ( int ) ac . second . overridden ,
ac . second . internalBezier , ac . second . internalEnabled , ac . second . internalSpeed , ac . second . internalStyle ) ;
2023-01-25 15:16:28 +00:00
}
ret + = " beziers: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & bz : g_pAnimationManager - > getAllBeziers ( ) ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format ( " \n \t name: {} \n " , bz . first ) ;
2023-01-25 15:16:28 +00:00
}
} else {
// json
ret + = " [[ " ;
2024-08-26 20:24:30 +02:00
for ( auto const & ac : g_pConfigManager - > getAnimationConfig ( ) ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format ( R " #(
2023-09-06 12:51:36 +02:00
{ {
" name " : " {} " ,
" overridden " : { } ,
" bezier " : " {} " ,
" enabled " : { } ,
" speed " : { : .2f } ,
" style " : " {} "
} } , ) # " ,
2024-04-30 22:13:36 +09:00
ac . first , ac . second . overridden ? " true " : " false " , escapeJSONStrings ( ac . second . internalBezier ) , ac . second . internalEnabled ? " true " : " false " ,
ac . second . internalSpeed , escapeJSONStrings ( ac . second . internalStyle ) ) ;
2023-01-25 15:16:28 +00:00
}
ret [ ret . length ( ) - 1 ] = ' ] ' ;
ret + = " , \n [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & bz : g_pAnimationManager - > getAllBeziers ( ) ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format ( R " #(
2023-09-06 12:51:36 +02:00
{ {
" name " : " {} "
} } , ) # " ,
2024-04-30 22:13:36 +09:00
escapeJSONStrings ( bz . first ) ) ;
2023-01-25 15:16:28 +00:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( ret ) ;
2023-01-25 15:16:28 +00:00
2023-02-11 20:54:32 +00:00
ret + = " ]] " ;
2023-01-25 15:16:28 +00:00
}
return ret ;
}
2024-02-05 01:56:38 +00:00
std : : string rollinglogRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-11-14 20:06:04 +00:00
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-11-14 20:06:04 +00:00
result + = " [ \n \" log \" : \" " ;
result + = escapeJSONStrings ( Debug : : rollingLog ) ;
result + = " \" ] " ;
} else {
result = Debug : : rollingLog ;
}
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string globalShortcutsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-04-09 13:48:20 +01:00
std : : string ret = " " ;
2024-07-30 16:33:56 -05:00
const auto SHORTCUTS = PROTO : : globalShortcuts - > getAllShortcuts ( ) ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
2024-08-26 20:24:30 +02:00
for ( auto const & sh : SHORTCUTS )
2023-09-20 07:26:20 +00:00
ret + = std : : format ( " {}:{} -> {} \n " , sh . appid , sh . id , sh . description ) ;
2023-04-09 13:48:20 +01:00
} else {
ret + = " [ " ;
2024-08-26 17:25:39 +02:00
for ( auto const & sh : SHORTCUTS ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format ( R " #(
2023-09-06 12:51:36 +02:00
{ {
" name " : " {} " ,
" description " : " {} "
} } , ) # " ,
2023-09-20 07:26:20 +00:00
escapeJSONStrings ( sh . appid + " : " + sh . id ) , escapeJSONStrings ( sh . description ) ) ;
2023-04-09 13:48:20 +01:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( ret ) ;
2023-04-09 13:48:20 +01:00
ret + = " ] \n " ;
}
return ret ;
}
2024-02-05 01:56:38 +00:00
std : : string bindsRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-01-06 14:32:25 +01:00
std : : string ret = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
2024-08-26 20:24:30 +02:00
for ( auto const & kb : g_pKeybindManager - > m_lKeybinds ) {
2023-01-06 14:32:25 +01:00
ret + = " bind " ;
if ( kb . locked )
ret + = " l " ;
if ( kb . mouse )
ret + = " m " ;
if ( kb . release )
ret + = " r " ;
if ( kb . repeat )
ret + = " e " ;
2023-06-14 04:08:56 -07:00
if ( kb . nonConsuming )
ret + = " n " ;
2024-06-11 19:49:54 +02:00
if ( kb . hasDescription )
ret + = " d " ;
2023-01-06 14:32:25 +01:00
2024-06-11 19:49:54 +02:00
ret + = std : : format ( " \n \t modmask: {} \n \t submap: {} \n \t key: {} \n \t keycode: {} \n \t catchall: {} \n \t description: {} \n \t dispatcher: {} \n \t arg: {} \n \n " , kb . modmask , kb . submap ,
kb . key , kb . keycode , kb . catchAll , kb . description , kb . handler , kb . arg ) ;
2023-01-06 14:32:25 +01:00
}
} else {
// json
ret + = " [ " ;
2024-08-26 20:24:30 +02:00
for ( auto const & kb : g_pKeybindManager - > m_lKeybinds ) {
2023-09-20 07:26:20 +00:00
ret + = std : : format (
2023-01-06 14:32:25 +01:00
R " #(
2023-09-06 12:51:36 +02:00
{ {
" locked " : { } ,
" mouse " : { } ,
" release " : { } ,
" repeat " : { } ,
" non_consuming " : { } ,
2024-06-11 19:49:54 +02:00
" has_description " : { } ,
2023-09-06 12:51:36 +02:00
" modmask " : { } ,
" submap " : " {} " ,
" key " : " {} " ,
" keycode " : { } ,
2024-03-03 01:17:02 +01:00
" catch_all " : { } ,
2024-06-11 19:49:54 +02:00
" description " : " {} " ,
2023-09-06 12:51:36 +02:00
" dispatcher " : " {} " ,
" arg " : " {} "
} } , ) # " ,
2023-06-14 04:08:56 -07:00
kb . locked ? " true " : " false " , kb . mouse ? " true " : " false " , kb . release ? " true " : " false " , kb . repeat ? " true " : " false " , kb . nonConsuming ? " true " : " false " ,
2024-06-11 19:49:54 +02:00
kb . hasDescription ? " true " : " false " , kb . modmask , escapeJSONStrings ( kb . submap ) , escapeJSONStrings ( kb . key ) , kb . keycode , kb . catchAll ? " true " : " false " ,
escapeJSONStrings ( kb . description ) , escapeJSONStrings ( kb . handler ) , escapeJSONStrings ( kb . arg ) ) ;
2023-01-06 14:32:25 +01:00
}
2023-05-24 08:46:56 -07:00
trimTrailingComma ( ret ) ;
2023-01-06 14:32:25 +01:00
ret + = " ] " ;
}
return ret ;
}
2024-02-05 01:56:38 +00:00
std : : string versionRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-08-11 21:28:37 +02:00
2024-06-11 17:17:45 +02:00
auto commitMsg = trim ( GIT_COMMIT_MESSAGE ) ;
2023-07-23 19:43:15 +02:00
std : : replace ( commitMsg . begin ( ) , commitMsg . end ( ) , ' # ' , ' ' ) ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
2023-07-23 19:43:15 +02:00
std : : string result = " Hyprland, built from branch " + std : : string ( GIT_BRANCH ) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " ( " + commitMsg +
2024-04-05 00:44:21 +01:00
" ). \n Date: " + GIT_COMMIT_DATE + " \n Tag: " + GIT_TAG + " , commits: " + GIT_COMMITS + " \n \n flags: (if any) \n " ;
2022-04-22 18:14:25 +02:00
# ifdef LEGACY_RENDERER
2022-08-11 21:28:37 +02:00
result + = " legacyrenderer \n " ;
2022-04-22 18:14:25 +02:00
# endif
2023-12-26 13:14:12 +00:00
# ifndef ISDEBUG
2022-12-16 17:17:31 +00:00
result + = " debug \n " ;
2022-06-18 13:09:38 +02:00
# endif
2022-04-22 18:14:25 +02:00
# ifdef NO_XWAYLAND
2022-08-11 21:28:37 +02:00
result + = " no xwayland \n " ;
2022-04-22 18:14:25 +02:00
# endif
2022-08-11 21:28:37 +02:00
return result ;
} else {
2023-09-20 07:26:20 +00:00
std : : string result = std : : format (
2023-09-06 12:51:36 +02:00
R " #({{
" branch " : " {} " ,
" commit " : " {} " ,
" dirty " : { } ,
" commit_message " : " {} " ,
2023-12-17 14:29:58 +00:00
" commit_date " : " {} " ,
2023-09-06 12:51:36 +02:00
" tag " : " {} " ,
2024-04-29 16:10:22 +01:00
" commits " : " {} " ,
2022-12-16 17:17:31 +00:00
" flags " : [ ) # " ,
2024-04-05 00:44:21 +01:00
GIT_BRANCH , GIT_COMMIT_HASH , ( strcmp ( GIT_DIRTY , " dirty " ) = = 0 ? " true " : " false " ) , escapeJSONStrings ( commitMsg ) , GIT_COMMIT_DATE , GIT_TAG , GIT_COMMITS ) ;
2022-08-11 21:28:37 +02:00
# ifdef LEGACY_RENDERER
result + = " \" legacyrenderer \" , " ;
# endif
2023-12-26 13:14:12 +00:00
# ifndef ISDEBUG
2022-12-16 17:17:31 +00:00
result + = " \" debug \" , " ;
2022-08-11 21:28:37 +02:00
# endif
# ifdef NO_XWAYLAND
result + = " \" no xwayland \" , " ;
# endif
2023-05-24 08:46:56 -07:00
trimTrailingComma ( result ) ;
2022-08-11 21:28:37 +02:00
result + = " ] \n } " ;
return result ;
}
return " " ; // make the compiler happy
2022-04-22 18:14:25 +02:00
}
2024-02-05 01:56:38 +00:00
std : : string systemInfoRequest ( eHyprCtlOutputFormat format , std : : string request ) {
std : : string result = versionRequest ( eHyprCtlOutputFormat : : FORMAT_NORMAL , " " ) ;
2024-01-01 17:53:00 +01:00
result + = " \n \n System Information: \n " ;
struct utsname unameInfo ;
uname ( & unameInfo ) ;
result + = " System name: " + std : : string { unameInfo . sysname } + " \n " ;
result + = " Node name: " + std : : string { unameInfo . nodename } + " \n " ;
result + = " Release: " + std : : string { unameInfo . release } + " \n " ;
result + = " Version: " + std : : string { unameInfo . version } + " \n " ;
result + = " \n \n " ;
# if defined(__DragonFly__) || defined(__FreeBSD__)
const std : : string GPUINFO = execAndGet ( " pciconf -lv | fgrep -A4 vga " ) ;
2024-05-23 19:04:39 +03:00
# elif defined(__arm__) || defined(__aarch64__)
const std : : string GPUINFO = execAndGet ( " cat /proc/device-tree/soc*/gpu*/compatible " ) ;
2024-01-01 17:53:00 +01:00
# else
const std : : string GPUINFO = execAndGet ( " lspci -vnn | grep VGA " ) ;
# endif
2024-06-30 14:16:41 +03:00
result + = " GPU information: \n " + GPUINFO ;
if ( GPUINFO . contains ( " NVIDIA " ) & & std : : filesystem : : exists ( " /proc/driver/nvidia/version " ) )
result + = execAndGet ( " cat /proc/driver/nvidia/version | grep NVRM " ) ;
result + = " \n \n " ;
2024-01-01 17:53:00 +01:00
result + = " os-release: " + execAndGet ( " cat /etc/os-release " ) + " \n \n " ;
result + = " plugins: \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & pl : g_pPluginSystem - > getAllPlugins ( ) ) {
2024-01-01 17:53:00 +01:00
result + = std : : format ( " {} by {} ver {} \n " , pl - > name , pl - > author , pl - > version ) ;
}
2024-05-25 20:46:07 +00:00
if ( g_pHyprCtl - > m_sCurrentRequestParams . sysInfoConfig ) {
result + = " \n ======Config-Start====== \n " ;
result + = g_pConfigManager - > getConfigString ( ) ;
result + = " \n ======Config-End======== \n " ;
}
2024-01-01 17:53:00 +01:00
return result ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchRequest ( eHyprCtlOutputFormat format , std : : string in ) {
2022-04-21 16:11:29 +02:00
// get rid of the dispatch keyword
in = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
const auto DISPATCHSTR = in . substr ( 0 , in . find_first_of ( ' ' ) ) ;
2023-07-21 17:20:23 +02:00
auto DISPATCHARG = std : : string ( ) ;
if ( ( int ) in . find_first_of ( ' ' ) ! = - 1 )
DISPATCHARG = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
2022-04-21 16:11:29 +02:00
const auto DISPATCHER = g_pKeybindManager - > m_mDispatchers . find ( DISPATCHSTR ) ;
if ( DISPATCHER = = g_pKeybindManager - > m_mDispatchers . end ( ) )
return " Invalid dispatcher " ;
2024-08-24 11:45:53 -05:00
SDispatchResult res = DISPATCHER - > second ( DISPATCHARG ) ;
2022-04-21 16:11:29 +02:00
2024-08-24 11:45:53 -05:00
Debug : : log ( LOG , " Hyprctl: dispatcher {} : {}{} " , DISPATCHSTR , DISPATCHARG , res . success ? " " : " -> " + res . error ) ;
2022-04-21 21:48:37 +02:00
2024-08-24 11:45:53 -05:00
return res . success ? " ok " : res . error ;
2022-04-21 16:11:29 +02:00
}
2024-02-05 01:56:38 +00:00
std : : string dispatchKeyword ( eHyprCtlOutputFormat format , std : : string in ) {
2024-08-27 20:42:30 +02:00
// Find the first space to strip the keyword keyword
auto const firstSpacePos = in . find_first_of ( ' ' ) ;
if ( firstSpacePos = = std : : string : : npos ) // Handle the case where there's no space found (invalid input)
return " Invalid input: no space found " ;
// Strip the keyword
in = in . substr ( firstSpacePos + 1 ) ;
// Find the next space for the COMMAND and VALUE
auto const secondSpacePos = in . find_first_of ( ' ' ) ;
if ( secondSpacePos = = std : : string : : npos ) // Handle the case where there's no second space (invalid input)
return " Invalid input: command and value not properly formatted " ;
// Extract COMMAND and VALUE
const auto COMMAND = in . substr ( 0 , secondSpacePos ) ;
const auto VALUE = in . substr ( secondSpacePos + 1 ) ;
// If either COMMAND or VALUE is empty, handle accordingly
if ( COMMAND . empty ( ) | | VALUE . empty ( ) )
return " Invalid input: command or value is empty " ;
2022-04-21 16:56:27 +02:00
2024-02-18 15:00:34 +00:00
std : : string retval = g_pConfigManager - > parseKeyword ( COMMAND , VALUE ) ;
2022-04-21 16:56:27 +02:00
2024-02-19 12:45:05 +00:00
// if we are executing a dynamic source we have to reload everything, so every if will have a check for source.
if ( COMMAND = = " monitor " | | COMMAND = = " source " )
2022-04-21 21:36:45 +02:00
g_pConfigManager - > m_bWantsMonitorReload = true ; // for monitor keywords
2022-04-21 17:36:28 +02:00
2024-02-19 12:45:05 +00:00
if ( COMMAND . contains ( " input " ) | | COMMAND . contains ( " device " ) | | COMMAND = = " source " ) {
2022-12-16 17:17:31 +00:00
g_pInputManager - > setKeyboardLayout ( ) ; // update kb layout
g_pInputManager - > setPointerConfigs ( ) ; // update mouse cfgs
2022-10-07 16:03:52 +02:00
g_pInputManager - > setTouchDeviceConfigs ( ) ; // update touch device cfgs
2022-12-21 15:11:39 +00:00
g_pInputManager - > setTabletConfigs ( ) ; // update tablets
2022-08-20 18:57:30 +02:00
}
2022-04-22 14:11:52 +02:00
2024-03-03 18:39:20 +00:00
static auto PLAYOUT = CConfigValue < std : : string > ( " general:layout " ) ;
2024-02-18 15:00:34 +00:00
2022-07-16 22:44:29 +02:00
if ( COMMAND . contains ( " general:layout " ) )
2024-02-18 15:00:34 +00:00
g_pLayoutManager - > switchToLayout ( * PLAYOUT ) ; // update layout
2022-12-16 17:17:31 +00:00
2024-02-19 12:45:05 +00:00
if ( COMMAND . contains ( " decoration:screen_shader " ) | | COMMAND = = " source " )
2022-12-03 14:40:12 +00:00
g_pHyprOpenGL - > m_bReloadScreenShader = true ;
2022-07-16 22:44:29 +02:00
2024-02-19 12:45:05 +00:00
if ( COMMAND . contains ( " blur " ) | | COMMAND = = " source " ) {
2022-12-18 15:05:34 +00:00
for ( auto & [ m , rd ] : g_pHyprOpenGL - > m_mMonitorRenderResources ) {
rd . blurFBDirty = true ;
}
}
2023-01-12 12:14:57 +01:00
// decorations will probably need a repaint
2024-05-09 22:23:01 +01:00
if ( COMMAND . contains ( " decoration: " ) | | COMMAND . contains ( " border " ) | | COMMAND = = " workspace " | | COMMAND . contains ( " zoom_factor " ) | | COMMAND = = " source " ) {
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pCompositor - > m_vMonitors ) {
2023-01-12 12:14:57 +01:00
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ;
2023-01-24 14:04:01 +00:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > ID ) ;
}
2023-01-12 12:14:57 +01:00
}
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Hyprctl: keyword {} : {} " , COMMAND , VALUE ) ;
2022-04-21 21:48:37 +02:00
2022-09-25 20:07:48 +02:00
if ( retval = = " " )
2022-04-21 16:56:27 +02:00
return " ok " ;
return retval ;
}
2024-02-05 01:56:38 +00:00
std : : string reloadRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-09-25 20:07:48 +02:00
2022-08-14 23:26:18 +02:00
const auto REQMODE = request . substr ( request . find_last_of ( ' ' ) + 1 ) ;
2022-05-08 15:28:45 +02:00
g_pConfigManager - > m_bForceReload = true ;
2022-08-14 23:26:18 +02:00
if ( REQMODE = = " config-only " ) {
g_pConfigManager - > m_bNoMonitorReload = true ;
}
2022-09-13 15:36:49 +02:00
g_pConfigManager - > tick ( ) ;
2022-05-08 15:28:45 +02:00
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string killRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-06-27 13:42:20 +02:00
g_pInputManager - > setClickMode ( CLICKMODE_KILL ) ;
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string splashRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-07-10 15:41:26 +02:00
return g_pCompositor - > m_szCurrentSplash ;
}
2024-02-05 01:56:38 +00:00
std : : string cursorPosRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2022-10-26 13:19:37 +01:00
const auto CURSORPOS = g_pInputManager - > getMouseCoordsInternal ( ) . floor ( ) ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
2023-09-20 07:26:20 +00:00
return std : : format ( " {}, {} " , ( int ) CURSORPOS . x , ( int ) CURSORPOS . y ) ;
2022-10-26 13:19:37 +01:00
} else {
2023-09-20 07:26:20 +00:00
return std : : format ( R " #(
2023-09-06 12:51:36 +02:00
{ {
" x " : { } ,
" y " : { }
} }
2022-12-16 17:17:31 +00:00
) # " ,
2023-09-20 07:26:20 +00:00
( int ) CURSORPOS . x , ( int ) CURSORPOS . y ) ;
2022-10-26 13:19:37 +01:00
}
return " error " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchBatch ( eHyprCtlOutputFormat format , std : : string request ) {
2022-04-29 19:44:09 +02:00
// split by ;
2022-12-16 17:17:31 +00:00
request = request . substr ( 9 ) ;
2022-04-29 19:44:09 +02:00
std : : string curitem = " " ;
2022-12-16 17:17:31 +00:00
std : : string reply = " " ;
2022-04-29 19:44:09 +02:00
2022-12-16 17:17:31 +00:00
auto nextItem = [ & ] ( ) {
2022-04-29 19:44:09 +02:00
auto idx = request . find_first_of ( ' ; ' ) ;
if ( idx ! = std : : string : : npos ) {
curitem = request . substr ( 0 , idx ) ;
request = request . substr ( idx + 1 ) ;
} else {
curitem = request ;
request = " " ;
}
2024-06-11 17:17:45 +02:00
curitem = trim ( curitem ) ;
2022-04-29 19:44:09 +02:00
} ;
nextItem ( ) ;
2024-05-27 23:31:35 +03:00
const std : : string DELIMITER = " \n \n \n " ;
2024-02-12 16:16:00 +01:00
while ( curitem ! = " " | | request ! = " " ) {
2024-05-27 23:31:35 +03:00
reply + = g_pHyprCtl - > getReply ( curitem ) + DELIMITER ;
2022-04-29 19:44:09 +02:00
nextItem ( ) ;
}
2024-05-27 23:31:35 +03:00
return reply . substr ( 0 , std : : max ( static_cast < int > ( reply . size ( ) - DELIMITER . size ( ) ) , 0 ) ) ;
2022-04-29 19:44:09 +02:00
}
2024-02-05 01:56:38 +00:00
std : : string dispatchSetCursor ( eHyprCtlOutputFormat format , std : : string request ) {
2023-05-02 06:51:52 -07:00
CVarList vars ( request , 0 , ' ' ) ;
2023-04-20 23:59:31 +01:00
2023-05-02 06:51:52 -07:00
const auto SIZESTR = vars [ vars . size ( ) - 1 ] ;
std : : string theme = " " ;
2023-04-20 23:59:31 +01:00
for ( size_t i = 1 ; i < vars . size ( ) - 1 ; + + i )
theme + = vars [ i ] + " " ;
2023-09-23 13:26:35 +01:00
if ( ! theme . empty ( ) )
theme . pop_back ( ) ;
2023-04-20 23:59:31 +01:00
int size = 0 ;
try {
size = std : : stoi ( SIZESTR ) ;
2023-05-02 06:51:52 -07:00
} catch ( . . . ) { return " size not int " ; }
2022-08-10 21:22:11 +02:00
2023-04-20 23:59:31 +01:00
if ( size < = 0 )
return " size not positive " ;
2022-08-10 21:22:11 +02:00
2024-05-28 16:35:18 -05:00
if ( ! g_pCursorManager - > changeTheme ( theme , size ) )
return " failed to set cursor " ;
2022-08-10 21:22:11 +02:00
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string switchXKBLayoutRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2024-08-28 14:05:31 +02:00
CVarList vars ( request , 0 , ' ' ) ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
const auto KB = vars [ 1 ] ;
const auto CMD = vars [ 2 ] ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
SP < IKeyboard > pKeyboard ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
auto updateKeyboard = [ ] ( const SP < IKeyboard > KEEB , const std : : string & CMD ) - > std : : optional < std : : string > {
const auto LAYOUTS = xkb_keymap_num_layouts ( KEEB - > xkbKeymap ) ;
xkb_layout_index_t activeLayout = 0 ;
while ( activeLayout < LAYOUTS ) {
if ( xkb_state_layout_index_is_active ( KEEB - > xkbState , activeLayout , XKB_STATE_LAYOUT_EFFECTIVE ) = = 1 )
break ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
activeLayout + + ;
}
2024-07-21 13:09:54 +02:00
2024-08-28 14:05:31 +02:00
if ( CMD = = " next " )
KEEB - > updateModifiers ( KEEB - > modifiersState . depressed , KEEB - > modifiersState . latched , KEEB - > modifiersState . locked , activeLayout > LAYOUTS ? 0 : activeLayout + 1 ) ;
else if ( CMD = = " prev " )
KEEB - > updateModifiers ( KEEB - > modifiersState . depressed , KEEB - > modifiersState . latched , KEEB - > modifiersState . locked , activeLayout = = 0 ? LAYOUTS - 1 : activeLayout - 1 ) ;
else {
int requestedLayout = 0 ;
try {
requestedLayout = std : : stoi ( CMD ) ;
} catch ( std : : exception & e ) { return " invalid arg 2 " ; }
if ( requestedLayout < 0 | | ( uint64_t ) requestedLayout > LAYOUTS - 1 ) {
return " layout idx out of range of " + std : : to_string ( LAYOUTS ) ;
}
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
KEEB - > updateModifiers ( KEEB - > modifiersState . depressed , KEEB - > modifiersState . latched , KEEB - > modifiersState . locked , requestedLayout ) ;
}
return std : : nullopt ;
} ;
if ( KB = = " main " | | KB = = " active " | | KB = = " current " ) {
for ( auto const & k : g_pInputManager - > m_vKeyboards ) {
if ( ! k - > active )
continue ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
pKeyboard = k ;
break ;
2022-12-03 15:56:07 +00:00
}
2024-08-28 14:05:31 +02:00
} else if ( KB = = " all " ) {
std : : string result = " " ;
for ( auto const & k : g_pInputManager - > m_vKeyboards ) {
auto res = updateKeyboard ( k , CMD ) ;
if ( res . has_value ( ) )
result + = * res + " \n " ;
}
return result . empty ( ) ? " ok " : result ;
} else {
auto k = std : : find_if ( g_pInputManager - > m_vKeyboards . begin ( ) , g_pInputManager - > m_vKeyboards . end ( ) ,
[ & ] ( const auto & other ) { return other - > hlName = = g_pInputManager - > deviceNameToInternalString ( KB ) ; } ) ;
2022-12-03 15:56:07 +00:00
2024-08-28 14:05:31 +02:00
if ( k = = g_pInputManager - > m_vKeyboards . end ( ) )
return " device not found " ;
pKeyboard = * k ;
2022-12-03 15:56:07 +00:00
}
2024-08-28 14:05:31 +02:00
if ( ! pKeyboard )
return " no device " ;
auto result = updateKeyboard ( pKeyboard , CMD ) ;
if ( result . has_value ( ) )
return * result ;
2022-12-03 15:56:07 +00:00
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchSeterror ( eHyprCtlOutputFormat format , std : : string request ) {
2023-01-22 16:38:17 +01:00
CVarList vars ( request , 0 , ' ' ) ;
std : : string errorMessage = " " ;
if ( vars . size ( ) < 3 ) {
g_pHyprError - > destroy ( ) ;
2023-01-22 16:51:32 +01:00
if ( vars . size ( ) = = 2 & & ! vars [ 1 ] . find ( " dis " ) )
return " var 1 not color or disable " ;
2023-01-22 16:38:17 +01:00
return " ok " ;
}
const CColor COLOR = configStringToInt ( vars [ 1 ] ) ;
for ( size_t i = 2 ; i < vars . size ( ) ; + + i )
errorMessage + = vars [ i ] + ' ' ;
if ( errorMessage . empty ( ) ) {
g_pHyprError - > destroy ( ) ;
} else {
errorMessage . pop_back ( ) ; // pop last space
g_pHyprError - > queueCreate ( errorMessage , COLOR ) ;
}
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchSetProp ( eHyprCtlOutputFormat format , std : : string request ) {
2023-01-24 19:05:34 +00:00
CVarList vars ( request , 0 , ' ' ) ;
if ( vars . size ( ) < 4 )
return " not enough args " ;
2024-04-27 12:43:12 +01:00
const auto PLASTWINDOW = g_pCompositor - > m_pLastWindow . lock ( ) ;
2024-02-13 13:07:19 -05:00
const auto PWINDOW = g_pCompositor - > getWindowByRegex ( vars [ 1 ] ) ;
2023-01-24 19:05:34 +00:00
if ( ! PWINDOW )
return " window not found " ;
const auto PROP = vars [ 2 ] ;
const auto VAL = vars [ 3 ] ;
2024-07-11 14:10:42 +00:00
bool noFocus = PWINDOW - > m_sWindowData . noFocus . valueOrDefault ( ) ;
2023-01-24 19:05:34 +00:00
try {
if ( PROP = = " animationstyle " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . animationStyle = CWindowOverridableVar ( VAL , PRIORITY_SET_PROP ) ;
2024-03-07 21:24:44 -05:00
} else if ( PROP = = " maxsize " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . maxSize = CWindowOverridableVar ( configStringToVector2D ( VAL + " " + vars [ 4 ] ) , PRIORITY_SET_PROP ) ;
PWINDOW - > m_vRealSize = Vector2D ( std : : min ( ( double ) PWINDOW - > m_sWindowData . maxSize . value ( ) . x , PWINDOW - > m_vRealSize . goal ( ) . x ) ,
std : : min ( ( double ) PWINDOW - > m_sWindowData . maxSize . value ( ) . y , PWINDOW - > m_vRealSize . goal ( ) . y ) ) ;
g_pXWaylandManager - > setWindowSize ( PWINDOW , PWINDOW - > m_vRealSize . goal ( ) ) ;
PWINDOW - > setHidden ( false ) ;
2024-03-07 21:24:44 -05:00
} else if ( PROP = = " minsize " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . minSize = CWindowOverridableVar ( configStringToVector2D ( VAL + " " + vars [ 4 ] ) , PRIORITY_SET_PROP ) ;
PWINDOW - > m_vRealSize = Vector2D ( std : : max ( ( double ) PWINDOW - > m_sWindowData . minSize . value ( ) . x , PWINDOW - > m_vRealSize . goal ( ) . x ) ,
std : : max ( ( double ) PWINDOW - > m_sWindowData . minSize . value ( ) . y , PWINDOW - > m_vRealSize . goal ( ) . y ) ) ;
g_pXWaylandManager - > setWindowSize ( PWINDOW , PWINDOW - > m_vRealSize . goal ( ) ) ;
PWINDOW - > setHidden ( false ) ;
2023-01-24 19:05:34 +00:00
} else if ( PROP = = " alpha " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . alpha = CWindowOverridableVar ( SAlphaValue { std : : stof ( VAL ) , PWINDOW - > m_sWindowData . alpha . valueOrDefault ( ) . m_bOverride } , PRIORITY_SET_PROP ) ;
2023-01-24 19:05:34 +00:00
} else if ( PROP = = " alphainactive " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . alphaInactive =
CWindowOverridableVar ( SAlphaValue { std : : stof ( VAL ) , PWINDOW - > m_sWindowData . alphaInactive . valueOrDefault ( ) . m_bOverride } , PRIORITY_SET_PROP ) ;
2024-04-08 01:19:02 +03:00
} else if ( PROP = = " alphafullscreen " ) {
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . alphaFullscreen =
CWindowOverridableVar ( SAlphaValue { std : : stof ( VAL ) , PWINDOW - > m_sWindowData . alphaFullscreen . valueOrDefault ( ) . m_bOverride } , PRIORITY_SET_PROP ) ;
} else if ( PROP = = " alphaoverride " ) {
PWINDOW - > m_sWindowData . alpha =
CWindowOverridableVar ( SAlphaValue { PWINDOW - > m_sWindowData . alpha . valueOrDefault ( ) . m_fAlpha , ( bool ) configStringToInt ( VAL ) } , PRIORITY_SET_PROP ) ;
} else if ( PROP = = " alphainactiveoverride " ) {
PWINDOW - > m_sWindowData . alphaInactive =
CWindowOverridableVar ( SAlphaValue { PWINDOW - > m_sWindowData . alphaInactive . valueOrDefault ( ) . m_fAlpha , ( bool ) configStringToInt ( VAL ) } , PRIORITY_SET_PROP ) ;
} else if ( PROP = = " alphafullscreenoverride " ) {
PWINDOW - > m_sWindowData . alphaFullscreen =
CWindowOverridableVar ( SAlphaValue { PWINDOW - > m_sWindowData . alphaFullscreen . valueOrDefault ( ) . m_fAlpha , ( bool ) configStringToInt ( VAL ) } , PRIORITY_SET_PROP ) ;
2024-04-09 18:14:53 +03:00
} else if ( PROP = = " activebordercolor " | | PROP = = " inactivebordercolor " ) {
CGradientValueData colorData = { } ;
if ( vars . size ( ) > 4 ) {
2024-07-11 14:10:42 +00:00
for ( int i = 3 ; i < static_cast < int > ( vars . size ( ) ) ; + + i ) {
2024-04-09 18:14:53 +03:00
const auto TOKEN = vars [ i ] ;
if ( TOKEN . ends_with ( " deg " ) )
colorData . m_fAngle = std : : stoi ( TOKEN . substr ( 0 , TOKEN . size ( ) - 3 ) ) * ( PI / 180.0 ) ;
else
colorData . m_vColors . push_back ( configStringToInt ( TOKEN ) ) ;
}
} else if ( VAL ! = " -1 " )
colorData . m_vColors . push_back ( configStringToInt ( VAL ) ) ;
if ( PROP = = " activebordercolor " )
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . activeBorderColor = CWindowOverridableVar ( colorData , PRIORITY_SET_PROP ) ;
2024-04-09 18:14:53 +03:00
else
2024-07-11 14:10:42 +00:00
PWINDOW - > m_sWindowData . inactiveBorderColor = CWindowOverridableVar ( colorData , PRIORITY_SET_PROP ) ;
} else if ( auto search = g_pConfigManager - > mbWindowProperties . find ( PROP ) ; search ! = g_pConfigManager - > mbWindowProperties . end ( ) ) {
auto pWindowDataElement = search - > second ( PWINDOW ) ;
if ( VAL = = " toggle " )
* pWindowDataElement = CWindowOverridableVar ( ! pWindowDataElement - > valueOrDefault ( ) , PRIORITY_SET_PROP ) ;
else if ( VAL = = " unset " )
pWindowDataElement - > unset ( PRIORITY_SET_PROP ) ;
else
* pWindowDataElement = CWindowOverridableVar ( ( bool ) configStringToInt ( VAL ) , PRIORITY_SET_PROP ) ;
} else if ( auto search = g_pConfigManager - > miWindowProperties . find ( PROP ) ; search ! = g_pConfigManager - > miWindowProperties . end ( ) ) {
if ( VAL = = " unset " )
search - > second ( PWINDOW ) - > unset ( PRIORITY_SET_PROP ) ;
else
* ( search - > second ( PWINDOW ) ) = CWindowOverridableVar ( ( int ) configStringToInt ( VAL ) , PRIORITY_SET_PROP ) ;
2023-01-24 19:05:34 +00:00
} else {
return " prop not found " ;
}
} catch ( std : : exception & e ) { return " error in parsing prop value: " + std : : string ( e . what ( ) ) ; }
2023-01-24 23:52:00 +00:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2024-07-11 14:10:42 +00:00
if ( ! ( PWINDOW - > m_sWindowData . noFocus . valueOrDefault ( ) = = noFocus ) ) {
2024-02-13 13:07:19 -05:00
g_pCompositor - > focusWindow ( nullptr ) ;
g_pCompositor - > focusWindow ( PWINDOW ) ;
g_pCompositor - > focusWindow ( PLASTWINDOW ) ;
}
2024-08-26 17:25:39 +02:00
for ( auto const & m : g_pCompositor - > m_vMonitors )
2023-06-04 21:35:17 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > ID ) ;
2023-01-24 19:05:34 +00:00
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchGetOption ( eHyprCtlOutputFormat format , std : : string request ) {
2022-08-11 21:16:38 +02:00
std : : string curitem = " " ;
2022-12-16 17:17:31 +00:00
auto nextItem = [ & ] ( ) {
2022-08-11 21:16:38 +02:00
auto idx = request . find_first_of ( ' ' ) ;
if ( idx ! = std : : string : : npos ) {
curitem = request . substr ( 0 , idx ) ;
request = request . substr ( idx + 1 ) ;
} else {
curitem = request ;
request = " " ;
}
2024-06-11 17:17:45 +02:00
curitem = trim ( curitem ) ;
2022-08-11 21:16:38 +02:00
} ;
nextItem ( ) ;
nextItem ( ) ;
2024-02-18 15:00:34 +00:00
const auto VAR = g_pConfigManager - > getHyprlangConfigValuePtr ( curitem ) ;
2022-08-11 21:16:38 +02:00
2024-02-18 15:00:34 +00:00
if ( ! VAR )
2022-08-11 21:16:38 +02:00
return " no such option " ;
2024-02-18 15:00:34 +00:00
const auto VAL = VAR - > getValue ( ) ;
const auto TYPE = std : : type_index ( VAL . type ( ) ) ;
if ( format = = FORMAT_NORMAL ) {
if ( TYPE = = typeid ( Hyprlang : : INT ) )
return std : : format ( " int: {} \n set: {} " , std : : any_cast < Hyprlang : : INT > ( VAL ) , VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : FLOAT ) )
return std : : format ( " float: {:2f} \n set: {} " , std : : any_cast < Hyprlang : : FLOAT > ( VAL ) , VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : VEC2 ) )
return std : : format ( " vec2: [{}, {}] \n set: {} " , std : : any_cast < Hyprlang : : VEC2 > ( VAL ) . x , std : : any_cast < Hyprlang : : VEC2 > ( VAL ) . y , VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : STRING ) )
return std : : format ( " str: {} \n set: {} " , std : : any_cast < Hyprlang : : STRING > ( VAL ) , VAR - > m_bSetByUser ) ;
2024-03-04 10:36:32 +00:00
else if ( TYPE = = typeid ( void * ) )
return std : : format ( " custom type: {} \n set: {} " , ( ( ICustomConfigValueData * ) std : : any_cast < void * > ( VAL ) ) - > toString ( ) , VAR - > m_bSetByUser ) ;
2024-02-18 15:00:34 +00:00
} else {
if ( TYPE = = typeid ( Hyprlang : : INT ) )
return std : : format ( " {{ \" option \" : \" {} \" , \" int \" : {}, \" set \" : {} }} " , curitem , std : : any_cast < Hyprlang : : INT > ( VAL ) , VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : FLOAT ) )
return std : : format ( " {{ \" option \" : \" {} \" , \" float \" : {:2f}, \" set \" : {} }} " , curitem , std : : any_cast < Hyprlang : : FLOAT > ( VAL ) , VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : VEC2 ) )
return std : : format ( " {{ \" option \" : \" {} \" , \" vec2 \" : [{},{}], \" set \" : {} }} " , curitem , std : : any_cast < Hyprlang : : VEC2 > ( VAL ) . x , std : : any_cast < Hyprlang : : VEC2 > ( VAL ) . y ,
VAR - > m_bSetByUser ) ;
else if ( TYPE = = typeid ( Hyprlang : : STRING ) )
return std : : format ( " {{ \" option \" : \" {} \" , \" str \" : \" {} \" , \" set \" : {} }} " , curitem , escapeJSONStrings ( std : : any_cast < Hyprlang : : STRING > ( VAL ) ) , VAR - > m_bSetByUser ) ;
2024-03-04 10:36:32 +00:00
else if ( TYPE = = typeid ( void * ) )
return std : : format ( " {{ \" option \" : \" {} \" , \" custom \" : \" {} \" , \" set \" : {} }} " , curitem , ( ( ICustomConfigValueData * ) std : : any_cast < void * > ( VAL ) ) - > toString ( ) ,
VAR - > m_bSetByUser ) ;
2022-08-11 21:16:38 +02:00
}
2024-02-18 15:00:34 +00:00
return " invalid type (internal error) " ;
2022-08-11 21:16:38 +02:00
}
2024-02-05 01:56:38 +00:00
std : : string decorationRequest ( eHyprCtlOutputFormat format , std : : string request ) {
2023-12-28 15:38:16 +00:00
CVarList vars ( request , 0 , ' ' ) ;
const auto PWINDOW = g_pCompositor - > getWindowByRegex ( vars [ 1 ] ) ;
if ( ! PWINDOW )
return " none " ;
std : : string result = " " ;
2024-02-05 01:56:38 +00:00
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON ) {
2023-12-28 15:38:16 +00:00
result + = " [ " ;
2024-08-26 20:24:30 +02:00
for ( auto const & wd : PWINDOW - > m_dWindowDecorations ) {
2023-12-28 15:38:16 +00:00
result + = " { \n \" decorationName \" : \" " + wd - > getDisplayName ( ) + " \" , \n \" priority \" : " + std : : to_string ( wd - > getPositioningInfo ( ) . priority ) + " \n }, " ;
}
trimTrailingComma ( result ) ;
result + = " ] " ;
} else {
result = + " Decoration \t Priority \n " ;
2024-08-26 20:24:30 +02:00
for ( auto const & wd : PWINDOW - > m_dWindowDecorations ) {
2023-12-28 15:38:16 +00:00
result + = wd - > getDisplayName ( ) + " \t " + std : : to_string ( wd - > getPositioningInfo ( ) . priority ) + " \n " ;
}
}
return result ;
}
2024-06-05 12:26:38 -04:00
std : : string dispatchOutput ( eHyprCtlOutputFormat format , std : : string request ) {
CVarList vars ( request , 0 , ' ' ) ;
2022-11-05 18:04:44 +00:00
2024-06-05 12:26:38 -04:00
if ( vars . size ( ) < 2 )
return " not enough args " ;
const auto MODE = vars [ 1 ] ;
2022-11-05 18:04:44 +00:00
2024-07-21 13:09:54 +02:00
bool added = false ;
if ( ! vars [ 3 ] . empty ( ) ) {
2024-08-26 17:25:39 +02:00
for ( auto const & m : g_pCompositor - > m_vRealMonitors ) {
2024-07-21 13:09:54 +02:00
if ( m - > szName = = vars [ 3 ] )
return " Name already taken " ;
}
}
2022-11-05 18:04:44 +00:00
if ( MODE = = " create " | | MODE = = " add " ) {
2024-06-05 12:26:38 -04:00
if ( g_pCompositor - > getMonitorFromName ( vars [ 3 ] ) )
return " A real monitor already uses that name. " ;
2024-08-26 20:24:30 +02:00
for ( auto const & impl : g_pCompositor - > m_pAqBackend - > getImplementations ( ) | std : : views : : reverse ) {
2024-07-21 13:09:54 +02:00
auto type = impl - > type ( ) ;
if ( type = = Aquamarine : : AQ_BACKEND_HEADLESS & & ( vars [ 2 ] = = " headless " | | vars [ 2 ] = = " auto " ) ) {
added = true ;
impl - > createOutput ( vars [ 3 ] ) ;
break ;
}
2022-11-05 18:04:44 +00:00
2024-07-21 13:09:54 +02:00
if ( type = = Aquamarine : : AQ_BACKEND_WAYLAND & & ( vars [ 2 ] = = " wayland " | | vars [ 2 ] = = " auto " ) ) {
added = true ;
impl - > createOutput ( vars [ 3 ] ) ;
break ;
}
}
2022-11-05 18:04:44 +00:00
2024-07-21 13:09:54 +02:00
if ( ! added )
2022-11-05 18:04:44 +00:00
return " no backend replied to the request " ;
} else if ( MODE = = " destroy " | | MODE = = " remove " ) {
2024-06-05 12:26:38 -04:00
const auto PMONITOR = g_pCompositor - > getMonitorFromName ( vars [ 2 ] ) ;
2022-11-05 18:04:44 +00:00
if ( ! PMONITOR )
return " output not found " ;
if ( ! PMONITOR - > createdByUser )
return " cannot remove a real display. Use the monitor keyword. " ;
2024-07-21 13:09:54 +02:00
PMONITOR - > output - > destroy ( ) ;
2022-11-05 18:04:44 +00:00
}
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchPlugin ( eHyprCtlOutputFormat format , std : : string request ) {
2023-02-27 12:32:38 +00:00
CVarList vars ( request , 0 , ' ' ) ;
if ( vars . size ( ) < 2 )
return " not enough args " ;
const auto OPERATION = vars [ 1 ] ;
const auto PATH = vars [ 2 ] ;
if ( OPERATION = = " load " ) {
if ( vars . size ( ) < 3 )
return " not enough args " ;
const auto PLUGIN = g_pPluginSystem - > loadPlugin ( PATH ) ;
if ( ! PLUGIN )
2023-11-17 22:22:31 +00:00
return " error in loading plugin, last error: " + g_pPluginSystem - > m_szLastError ;
2023-02-27 12:32:38 +00:00
} else if ( OPERATION = = " unload " ) {
if ( vars . size ( ) < 3 )
return " not enough args " ;
const auto PLUGIN = g_pPluginSystem - > getPluginByPath ( PATH ) ;
if ( ! PLUGIN )
return " plugin not loaded " ;
g_pPluginSystem - > unloadPlugin ( PLUGIN ) ;
} else if ( OPERATION = = " list " ) {
2024-03-31 22:45:22 +02:00
const auto PLUGINS = g_pPluginSystem - > getAllPlugins ( ) ;
if ( PLUGINS . size ( ) = = 0 )
return " no plugins loaded " ;
2023-02-27 12:32:38 +00:00
std : : string list = " " ;
2024-08-26 20:24:30 +02:00
for ( auto const & p : PLUGINS ) {
2023-09-20 07:26:20 +00:00
list + = std : : format ( " \n Plugin {} by {}: \n \t Handle: {:x} \n \t Version: {} \n \t Description: {} \n " , p - > name , p - > author , ( uintptr_t ) p - > m_pHandle , p - > version , p - > description ) ;
2023-02-27 12:32:38 +00:00
}
return list ;
} else {
return " unknown opt " ;
}
return " ok " ;
}
2024-02-05 01:56:38 +00:00
std : : string dispatchNotify ( eHyprCtlOutputFormat format , std : : string request ) {
2023-03-20 16:00:54 +00:00
CVarList vars ( request , 0 , ' ' ) ;
if ( vars . size ( ) < 5 )
return " not enough args " ;
const auto ICON = vars [ 1 ] ;
if ( ! isNumber ( ICON ) )
return " invalid arg 1 " ;
int icon = - 1 ;
try {
icon = std : : stoi ( ICON ) ;
} catch ( std : : exception & e ) { return " invalid arg 1 " ; }
2023-04-08 18:53:54 +01:00
if ( icon > ICON_NONE | | icon < 0 ) {
2023-03-20 16:00:54 +00:00
icon = ICON_NONE ;
}
const auto TIME = vars [ 2 ] ;
int time = 0 ;
try {
time = std : : stoi ( TIME ) ;
} catch ( std : : exception & e ) { return " invalid arg 2 " ; }
2024-03-06 22:20:26 +01:00
CColor color = configStringToInt ( vars [ 3 ] ) ;
2023-03-20 16:00:54 +00:00
2024-03-06 22:20:26 +01:00
size_t msgidx = 4 ;
float fontsize = 13.f ;
2024-03-08 00:34:33 +01:00
if ( vars [ msgidx ] . length ( ) > 9 & & vars [ msgidx ] . compare ( 0 , 9 , " fontsize: " ) = = 0 ) {
2024-03-06 22:20:26 +01:00
const auto FONTSIZE = vars [ msgidx ] . substr ( 9 ) ;
2023-03-20 16:00:54 +00:00
2024-03-06 22:20:26 +01:00
if ( ! isNumber ( FONTSIZE , true ) )
return " invalid fontsize kwarg " ;
try {
fontsize = std : : stoi ( FONTSIZE ) ;
} catch ( std : : exception & e ) { return " invalid fontsize karg " ; }
+ + msgidx ;
2023-03-20 16:00:54 +00:00
}
2024-03-06 22:20:26 +01:00
if ( vars . size ( ) < = msgidx )
return " not enough args " ;
const auto MESSAGE = vars . join ( " " , msgidx ) ;
2023-03-20 16:00:54 +00:00
2024-03-06 22:20:26 +01:00
g_pHyprNotificationOverlay - > addNotification ( MESSAGE , color , time , ( eIcons ) icon , fontsize ) ;
2023-03-20 16:00:54 +00:00
return " ok " ;
}
2024-03-02 19:12:31 +01:00
std : : string dispatchDismissNotify ( eHyprCtlOutputFormat format , std : : string request ) {
CVarList vars ( request , 0 , ' ' ) ;
int amount = - 1 ;
if ( vars . size ( ) > 1 ) {
const auto AMOUNT = vars [ 1 ] ;
if ( ! isNumber ( AMOUNT ) )
return " invalid arg 1 " ;
try {
amount = std : : stoi ( AMOUNT ) ;
} catch ( std : : exception & e ) { return " invalid arg 1 " ; }
}
g_pHyprNotificationOverlay - > dismissNotifications ( amount ) ;
return " ok " ;
}
2024-05-13 16:57:06 +03:00
std : : string getIsLocked ( eHyprCtlOutputFormat format , std : : string request ) {
std : : string lockedStr = g_pSessionLockManager - > isSessionLocked ( ) ? " true " : " false " ;
if ( format = = eHyprCtlOutputFormat : : FORMAT_JSON )
lockedStr = std : : format ( R " #(
{ {
" locked " : { }
} }
) # " ,
lockedStr ) ;
return lockedStr ;
}
2024-08-17 17:33:16 +01:00
std : : string getDescriptions ( eHyprCtlOutputFormat format , std : : string request ) {
std : : string json = " { " ;
const auto & DESCS = g_pConfigManager - > getAllDescriptions ( ) ;
for ( const auto & d : DESCS ) {
json + = d . jsonify ( ) + " , \n " ;
}
json . pop_back ( ) ;
json . pop_back ( ) ;
json + = " } \n " ;
return json ;
}
2024-02-05 01:43:45 +00:00
CHyprCtl : : CHyprCtl ( ) {
2024-02-05 01:56:38 +00:00
registerCommand ( SHyprCtlCommand { " workspaces " , true , workspacesRequest } ) ;
registerCommand ( SHyprCtlCommand { " workspacerules " , true , workspaceRulesRequest } ) ;
registerCommand ( SHyprCtlCommand { " activeworkspace " , true , activeWorkspaceRequest } ) ;
registerCommand ( SHyprCtlCommand { " clients " , true , clientsRequest } ) ;
registerCommand ( SHyprCtlCommand { " kill " , true , killRequest } ) ;
registerCommand ( SHyprCtlCommand { " activewindow " , true , activeWindowRequest } ) ;
registerCommand ( SHyprCtlCommand { " layers " , true , layersRequest } ) ;
registerCommand ( SHyprCtlCommand { " version " , true , versionRequest } ) ;
registerCommand ( SHyprCtlCommand { " devices " , true , devicesRequest } ) ;
registerCommand ( SHyprCtlCommand { " splash " , true , splashRequest } ) ;
registerCommand ( SHyprCtlCommand { " cursorpos " , true , cursorPosRequest } ) ;
registerCommand ( SHyprCtlCommand { " binds " , true , bindsRequest } ) ;
registerCommand ( SHyprCtlCommand { " globalshortcuts " , true , globalShortcutsRequest } ) ;
registerCommand ( SHyprCtlCommand { " systeminfo " , true , systemInfoRequest } ) ;
registerCommand ( SHyprCtlCommand { " animations " , true , animationsRequest } ) ;
registerCommand ( SHyprCtlCommand { " rollinglog " , true , rollinglogRequest } ) ;
registerCommand ( SHyprCtlCommand { " layouts " , true , layoutsRequest } ) ;
2024-03-20 21:55:13 -04:00
registerCommand ( SHyprCtlCommand { " configerrors " , true , configErrorsRequest } ) ;
2024-05-13 16:57:06 +03:00
registerCommand ( SHyprCtlCommand { " locked " , true , getIsLocked } ) ;
2024-08-17 17:33:16 +01:00
registerCommand ( SHyprCtlCommand { " descriptions " , true , getDescriptions } ) ;
2024-02-05 01:56:38 +00:00
registerCommand ( SHyprCtlCommand { " monitors " , false , monitorsRequest } ) ;
registerCommand ( SHyprCtlCommand { " reload " , false , reloadRequest } ) ;
registerCommand ( SHyprCtlCommand { " plugin " , false , dispatchPlugin } ) ;
registerCommand ( SHyprCtlCommand { " notify " , false , dispatchNotify } ) ;
2024-03-02 19:12:31 +01:00
registerCommand ( SHyprCtlCommand { " dismissnotify " , false , dispatchDismissNotify } ) ;
2024-02-05 01:56:38 +00:00
registerCommand ( SHyprCtlCommand { " setprop " , false , dispatchSetProp } ) ;
registerCommand ( SHyprCtlCommand { " seterror " , false , dispatchSeterror } ) ;
registerCommand ( SHyprCtlCommand { " switchxkblayout " , false , switchXKBLayoutRequest } ) ;
registerCommand ( SHyprCtlCommand { " output " , false , dispatchOutput } ) ;
registerCommand ( SHyprCtlCommand { " dispatch " , false , dispatchRequest } ) ;
registerCommand ( SHyprCtlCommand { " keyword " , false , dispatchKeyword } ) ;
registerCommand ( SHyprCtlCommand { " setcursor " , false , dispatchSetCursor } ) ;
registerCommand ( SHyprCtlCommand { " getoption " , false , dispatchGetOption } ) ;
registerCommand ( SHyprCtlCommand { " decorations " , false , decorationRequest } ) ;
registerCommand ( SHyprCtlCommand { " [[BATCH]] " , false , dispatchBatch } ) ;
2024-02-05 01:43:45 +00:00
startHyprCtlSocket ( ) ;
}
2024-06-02 18:42:54 +02:00
CHyprCtl : : ~ CHyprCtl ( ) {
if ( m_eventSource )
wl_event_source_remove ( m_eventSource ) ;
2024-07-31 21:00:14 +02:00
if ( m_iSocketFD > = 0 )
close ( m_iSocketFD ) ;
if ( ! m_socketPath . empty ( ) )
unlink ( m_socketPath . c_str ( ) ) ;
2024-06-02 18:42:54 +02:00
}
2024-05-05 17:16:00 +01:00
SP < SHyprCtlCommand > CHyprCtl : : registerCommand ( SHyprCtlCommand cmd ) {
return m_vCommands . emplace_back ( makeShared < SHyprCtlCommand > ( cmd ) ) ;
2024-02-05 01:43:45 +00:00
}
2024-05-05 17:16:00 +01:00
void CHyprCtl : : unregisterCommand ( const SP < SHyprCtlCommand > & cmd ) {
2024-02-05 01:43:45 +00:00
std : : erase ( m_vCommands , cmd ) ;
}
std : : string CHyprCtl : : getReply ( std : : string request ) {
2024-03-08 17:47:12 +00:00
auto format = eHyprCtlOutputFormat : : FORMAT_NORMAL ;
bool reloadAll = false ;
m_sCurrentRequestParams = { } ;
2022-07-12 14:59:36 -06:00
2022-07-12 16:34:28 -06:00
// process flags for non-batch requests
2024-01-14 17:12:52 +00:00
if ( ! request . starts_with ( " [[BATCH]] " ) & & request . contains ( " / " ) ) {
2022-07-13 15:48:47 +02:00
long unsigned int sepIndex = 0 ;
2022-07-12 16:34:28 -06:00
for ( const auto & c : request ) {
if ( c = = ' / ' ) { // stop at separator
break ;
}
2024-01-14 17:12:52 +00:00
// after whitespace assume the first word as a keyword,
// so its value can have slashes (e.g., a path)
if ( c = = ' ' ) {
sepIndex = request . size ( ) ;
break ;
}
2022-07-12 16:34:28 -06:00
sepIndex + + ;
2022-09-25 20:07:48 +02:00
2022-07-12 16:34:28 -06:00
if ( c = = ' j ' )
2024-02-05 01:56:38 +00:00
format = eHyprCtlOutputFormat : : FORMAT_JSON ;
2024-03-08 17:47:12 +00:00
else if ( c = = ' r ' )
2024-02-24 14:01:58 +00:00
reloadAll = true ;
2024-03-08 17:47:12 +00:00
else if ( c = = ' a ' )
m_sCurrentRequestParams . all = true ;
2024-05-25 20:46:07 +00:00
else if ( c = = ' c ' )
m_sCurrentRequestParams . sysInfoConfig = true ;
2022-07-12 14:59:36 -06:00
}
2022-07-12 16:34:28 -06:00
if ( sepIndex < request . size ( ) )
request = request . substr ( sepIndex + 1 ) ; // remove flags and separator so we can compare the rest of the string
2022-07-12 14:59:36 -06:00
}
2024-02-24 14:01:58 +00:00
std : : string result = " " ;
2024-02-05 01:43:45 +00:00
// parse exact cmds first, then non-exact.
2024-08-26 20:24:30 +02:00
for ( auto const & cmd : m_vCommands ) {
2024-02-05 01:43:45 +00:00
if ( ! cmd - > exact )
continue ;
2024-02-24 14:01:58 +00:00
if ( cmd - > name = = request ) {
result = cmd - > fn ( format , request ) ;
break ;
}
2024-02-05 01:43:45 +00:00
}
2024-02-24 14:01:58 +00:00
if ( result . empty ( ) )
2024-08-26 20:24:30 +02:00
for ( auto const & cmd : m_vCommands ) {
2024-02-24 14:01:58 +00:00
if ( cmd - > exact )
continue ;
2024-02-05 01:43:45 +00:00
2024-02-24 14:01:58 +00:00
if ( request . starts_with ( cmd - > name ) ) {
result = cmd - > fn ( format , request ) ;
break ;
}
}
if ( result . empty ( ) )
return " unknown request " ;
if ( reloadAll ) {
g_pConfigManager - > m_bWantsMonitorReload = true ; // for monitor keywords
g_pInputManager - > setKeyboardLayout ( ) ; // update kb layout
g_pInputManager - > setPointerConfigs ( ) ; // update mouse cfgs
g_pInputManager - > setTouchDeviceConfigs ( ) ; // update touch device cfgs
g_pInputManager - > setTabletConfigs ( ) ; // update tablets
2024-03-03 18:39:20 +00:00
static auto PLAYOUT = CConfigValue < std : : string > ( " general:layout " ) ;
2024-02-24 14:01:58 +00:00
g_pLayoutManager - > switchToLayout ( * PLAYOUT ) ; // update layout
g_pHyprOpenGL - > m_bReloadScreenShader = true ;
for ( auto & [ m , rd ] : g_pHyprOpenGL - > m_mMonitorRenderResources ) {
rd . blurFBDirty = true ;
}
2024-08-26 20:24:30 +02:00
for ( auto const & m : g_pCompositor - > m_vMonitors ) {
2024-02-24 14:01:58 +00:00
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > ID ) ;
}
2024-02-05 01:43:45 +00:00
}
2022-04-29 19:44:09 +02:00
2024-02-24 14:01:58 +00:00
return result ;
2022-04-29 19:44:09 +02:00
}
2024-02-05 01:43:45 +00:00
std : : string CHyprCtl : : makeDynamicCall ( const std : : string & input ) {
2023-02-27 12:32:38 +00:00
return getReply ( input ) ;
}
2024-06-14 13:11:40 +03:00
bool successWrite ( int fd , const std : : string & data , bool needLog = true ) {
if ( write ( fd , data . c_str ( ) , data . length ( ) ) > 0 )
return true ;
if ( errno = = EAGAIN )
return true ;
if ( needLog )
Debug : : log ( ERR , " Couldn't write to socket. Error: " + std : : string ( strerror ( errno ) ) ) ;
return false ;
}
void runWritingDebugLogThread ( const int conn ) {
using namespace std : : chrono_literals ;
Debug : : log ( LOG , " In followlog thread, got connection, start writing: {} " , conn ) ;
//will be finished, when reading side close connection
std : : thread ( [ conn ] ( ) {
while ( Debug : : RollingLogFollow : : Get ( ) . IsRunning ( ) ) {
if ( Debug : : RollingLogFollow : : Get ( ) . isEmpty ( conn ) ) {
std : : this_thread : : sleep_for ( 1000 ms ) ;
continue ;
}
auto line = Debug : : RollingLogFollow : : Get ( ) . GetLog ( conn ) ;
if ( ! successWrite ( conn , line ) )
// We cannot write, when connection is closed. So thread will successfully exit by itself
break ;
std : : this_thread : : sleep_for ( 100 ms ) ;
}
close ( conn ) ;
Debug : : RollingLogFollow : : Get ( ) . StopFor ( conn ) ;
} ) . detach ( ) ;
}
bool isFollowUpRollingLogRequest ( const std : : string & request ) {
return request . contains ( " rollinglog " ) & & request . contains ( " f " ) ;
}
2022-09-10 21:21:28 +02:00
int hyprCtlFDTick ( int fd , uint32_t mask , void * data ) {
if ( mask & WL_EVENT_ERROR | | mask & WL_EVENT_HANGUP )
return 0 ;
2023-11-13 16:30:37 +00:00
sockaddr_in clientAddress ;
socklen_t clientSize = sizeof ( clientAddress ) ;
2022-09-10 21:21:28 +02:00
2024-02-05 01:43:45 +00:00
const auto ACCEPTEDCONNECTION = accept4 ( g_pHyprCtl - > m_iSocketFD , ( sockaddr * ) & clientAddress , & clientSize , SOCK_CLOEXEC ) ;
2022-09-10 21:21:28 +02:00
2023-11-13 16:30:37 +00:00
std : : array < char , 1024 > readBuffer ;
2022-09-10 21:21:28 +02:00
2024-06-18 21:38:33 +02:00
//
pollfd pollfds [ 1 ] = {
{
. fd = ACCEPTEDCONNECTION ,
. events = POLLIN ,
} ,
} ;
int ret = poll ( pollfds , 1 , 5000 ) ;
2023-07-21 17:20:23 +02:00
2024-06-18 21:38:33 +02:00
if ( ret < = 0 ) {
2023-07-21 17:20:23 +02:00
close ( ACCEPTEDCONNECTION ) ;
return 0 ;
}
2023-11-13 16:30:37 +00:00
std : : string request ;
while ( true ) {
readBuffer . fill ( 0 ) ;
auto messageSize = read ( ACCEPTEDCONNECTION , readBuffer . data ( ) , 1023 ) ;
if ( messageSize < 1 )
break ;
std : : string recvd = readBuffer . data ( ) ;
request + = recvd ;
if ( messageSize < 1023 )
break ;
}
2022-04-21 22:00:03 +02:00
std : : string reply = " " ;
try {
2024-02-05 01:43:45 +00:00
reply = g_pHyprCtl - > getReply ( request ) ;
2022-04-21 22:00:03 +02:00
} catch ( std : : exception & e ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Error in request: {} " , e . what ( ) ) ;
2022-04-21 22:00:03 +02:00
reply = " Err: " + std : : string ( e . what ( ) ) ;
}
2024-06-14 13:11:40 +03:00
successWrite ( ACCEPTEDCONNECTION , reply ) ;
2022-04-21 22:00:03 +02:00
2024-06-14 13:11:40 +03:00
if ( isFollowUpRollingLogRequest ( request ) ) {
Debug : : log ( LOG , " Followup rollinglog request received. Starting thread to write to socket. " ) ;
Debug : : RollingLogFollow : : Get ( ) . StartFor ( ACCEPTEDCONNECTION ) ;
runWritingDebugLogThread ( ACCEPTEDCONNECTION ) ;
Debug : : log ( LOG , Debug : : RollingLogFollow : : Get ( ) . DebugInfo ( ) ) ;
} else
close ( ACCEPTEDCONNECTION ) ;
2022-08-03 17:12:38 +02:00
2024-02-05 01:43:45 +00:00
if ( g_pConfigManager - > m_bWantsMonitorReload )
2023-04-03 22:52:09 +01:00
g_pConfigManager - > ensureMonitorStatus ( ) ;
2022-04-21 22:00:03 +02:00
2022-09-10 21:21:28 +02:00
return 0 ;
2022-04-21 22:00:03 +02:00
}
2024-02-05 01:43:45 +00:00
void CHyprCtl : : startHyprCtlSocket ( ) {
m_iSocketFD = socket ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 ) ;
2022-03-21 18:29:41 +01:00
2024-02-05 01:43:45 +00:00
if ( m_iSocketFD < 0 ) {
2022-09-10 21:21:28 +02:00
Debug : : log ( ERR , " Couldn't start the Hyprland Socket. (1) IPC will not work. " ) ;
return ;
}
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
sockaddr_un SERVERADDRESS = { . sun_family = AF_UNIX } ;
2022-03-21 18:29:41 +01:00
2024-07-31 21:00:14 +02:00
m_socketPath = g_pCompositor - > m_szInstancePath + " /.socket.sock " ;
2022-03-21 18:29:41 +01:00
2024-07-31 21:00:14 +02:00
strcpy ( SERVERADDRESS . sun_path , m_socketPath . c_str ( ) ) ;
2022-03-21 18:29:41 +01:00
2024-02-05 01:43:45 +00:00
if ( bind ( m_iSocketFD , ( sockaddr * ) & SERVERADDRESS , SUN_LEN ( & SERVERADDRESS ) ) < 0 ) {
2022-12-16 17:17:31 +00:00
Debug : : log ( ERR , " Couldn't start the Hyprland Socket. (2) IPC will not work. " ) ;
return ;
}
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
// 10 max queued.
2024-02-05 01:43:45 +00:00
listen ( m_iSocketFD , 10 ) ;
2022-03-22 16:54:45 +01:00
2024-07-31 21:00:14 +02:00
Debug : : log ( LOG , " Hypr socket started at {} " , m_socketPath ) ;
2022-08-28 11:19:08 +02:00
2024-06-02 18:42:54 +02:00
m_eventSource = wl_event_loop_add_fd ( g_pCompositor - > m_sWLEventLoop , m_iSocketFD , WL_EVENT_READABLE , hyprCtlFDTick , nullptr ) ;
2022-08-04 16:25:56 -07:00
}