2022-03-20 16:51:14 +01:00
# include "HyprCtl.hpp"
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>
2022-05-24 19:42:43 +02:00
# include <sys/un.h>
2022-03-20 16:51:14 +01:00
# include <unistd.h>
2022-03-30 16:24:42 +02:00
# include <errno.h>
2022-03-20 16:51:14 +01:00
# include <string>
2022-07-12 22:59:36 +02:00
std : : string monitorsRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-03-20 16:51:14 +01:00
std : : string result = " " ;
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
result + = " [ " ;
2022-09-25 20:07:48 +02:00
2022-07-12 19:57:33 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
result + = getFormat (
R " #({
" id " : % i ,
" name " : " %s " ,
2022-10-05 11:22:33 +02:00
" description " : " %s " ,
2022-07-12 19:57:33 +02:00
" width " : % i ,
" height " : % i ,
" refreshRate " : % f ,
" x " : % i ,
" y " : % i ,
" activeWorkspace " : {
" id " : % i ,
" name " : " %s "
} ,
" reserved " : [ % i , % i , % i , % i ] ,
" scale " : % .2f ,
" transform " : % i ,
2022-10-05 19:14:11 +02:00
" focused " : % s ,
" dpmsStatus " : % s
2022-07-12 19:57:33 +02:00
} , ) # " ,
m - > ID ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( m - > szName ) . c_str ( ) ,
2022-10-05 11:22:33 +02:00
escapeJSONStrings ( m - > output - > description ? m - > output - > description : " " ) ,
2022-07-12 19:57:33 +02:00
( int ) m - > vecPixelSize . x , ( int ) m - > vecPixelSize . y ,
m - > refreshRate ,
( int ) m - > vecPosition . x , ( int ) m - > vecPosition . y ,
2022-07-18 20:47:28 +02:00
m - > activeWorkspace , escapeJSONStrings ( g_pCompositor - > getWorkspaceByID ( m - > activeWorkspace ) - > m_szName ) . c_str ( ) ,
2022-07-12 19:57:33 +02:00
( int ) m - > vecReservedTopLeft . x , ( int ) m - > vecReservedTopLeft . y , ( int ) m - > vecReservedBottomRight . x , ( int ) m - > vecReservedBottomRight . y ,
m - > scale ,
( int ) m - > transform ,
2022-10-05 19:14:11 +02:00
( m . get ( ) = = g_pCompositor - > m_pLastMonitor ? " true " : " false " ) ,
( m - > dpmsStatus ? " true " : " false " )
2022-07-12 19:57:33 +02:00
) ;
}
// remove trailing comma
result . pop_back ( ) ;
result + = " ] " ;
} else {
for ( auto & m : g_pCompositor - > m_vMonitors ) {
2022-10-05 19:14:11 +02:00
result + = getFormat ( " Monitor %s (ID %i): \n \t %ix%i@%f at %ix%i \n \t description: %s \n \t active workspace: %i (%s) \n \t reserved: %i %i %i %i \n \t scale: %.2f \n \t transform: %i \n \t focused: %s \n \t dpmsStatus: %i \n \n " ,
m - > szName . c_str ( ) , m - > ID , ( int ) m - > vecPixelSize . x , ( int ) m - > vecPixelSize . y , m - > refreshRate , ( int ) m - > vecPosition . x , ( int ) m - > vecPosition . y , ( m - > output - > description ? m - > output - > description : " " ) , m - > activeWorkspace , g_pCompositor - > getWorkspaceByID ( m - > activeWorkspace ) - > m_szName . c_str ( ) , ( int ) m - > vecReservedTopLeft . x , ( int ) m - > vecReservedTopLeft . y , ( int ) m - > vecReservedBottomRight . x , ( int ) m - > vecReservedBottomRight . y , m - > scale , ( int ) m - > transform , ( m . get ( ) = = g_pCompositor - > m_pLastMonitor ? " yes " : " no " ) , ( int ) m - > dpmsStatus ) ;
2022-07-12 19:57:33 +02:00
}
2022-03-20 16:51:14 +01:00
}
return result ;
}
2022-07-12 22:59:36 +02:00
std : : string clientsRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-03-20 16:51:14 +01:00
std : : string result = " " ;
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
result + = " [ " ;
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bIsMapped ) {
result + = getFormat (
R " #({
" address " : " 0x%x " ,
" at " : [ % i , % i ] ,
" size " : [ % i , % i ] ,
" workspace " : {
" id " : % i ,
" name " : " %s "
} ,
2022-08-06 00:23:38 +02:00
" floating " : % s ,
2022-07-12 19:57:33 +02:00
" monitor " : % i ,
" class " : " %s " ,
" title " : " %s " ,
2022-07-26 18:25:08 +02:00
" pid " : % i ,
2022-09-10 13:11:02 +02:00
" xwayland " : % s ,
2022-09-29 20:30:49 +02:00
" pinned " : % s ,
" fullscreen " : % s ,
" fullscreenMode " : % i
2022-07-12 19:57:33 +02:00
} , ) # " ,
2022-07-18 01:00:12 +02:00
w . get ( ) ,
2022-07-12 19:57:33 +02:00
( int ) w - > m_vRealPosition . vec ( ) . x , ( int ) w - > m_vRealPosition . vec ( ) . y ,
( int ) w - > m_vRealSize . vec ( ) . x , ( int ) w - > m_vRealSize . vec ( ) . y ,
2022-07-18 20:47:28 +02:00
w - > m_iWorkspaceID , escapeJSONStrings ( w - > m_iWorkspaceID = = - 1 ? " " : g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ? g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) - > m_szName : std : : string ( " Invalid workspace " + std : : to_string ( w - > m_iWorkspaceID ) ) ) . c_str ( ) ,
2022-08-06 00:23:38 +02:00
( ( int ) w - > m_bIsFloating = = 1 ? " true " : " false " ) ,
2022-07-12 19:57:33 +02:00
w - > m_iMonitorID ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( g_pXWaylandManager - > getAppIDClass ( w . get ( ) ) ) . c_str ( ) ,
escapeJSONStrings ( g_pXWaylandManager - > getTitle ( w . get ( ) ) ) . c_str ( ) ,
2022-07-26 18:25:08 +02:00
w - > getPID ( ) ,
2022-09-10 13:11:02 +02:00
( ( int ) w - > m_bIsX11 = = 1 ? " true " : " false " ) ,
2022-09-29 20:30:49 +02:00
( w - > m_bPinned ? " true " : " false " ) ,
( w - > m_bIsFullscreen ? " true " : " false " ) ,
( w - > m_bIsFullscreen ? ( g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ? g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) - > m_efFullscreenMode : 0 ) : 0 )
2022-07-12 19:57:33 +02:00
) ;
}
}
// remove trailing comma
2022-08-06 00:53:19 +02:00
if ( result ! = " [ " )
result . pop_back ( ) ;
2022-07-12 19:57:33 +02:00
result + = " ] " ;
} else {
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_bIsMapped ) {
2022-09-29 20:30:49 +02:00
result + = getFormat ( " Window %x -> %s: \n \t at: %i,%i \n \t size: %i,%i \n \t workspace: %i (%s) \n \t floating: %i \n \t monitor: %i \n \t class: %s \n \t title: %s \n \t pid: %i \n \t xwayland: %i \n \t pinned: %i \n \t fullscreen: %i \n \t fullscreenmode: %i \n \n " ,
w . get ( ) , w - > m_szTitle . c_str ( ) , ( int ) w - > m_vRealPosition . vec ( ) . x , ( int ) w - > m_vRealPosition . vec ( ) . y , ( int ) w - > m_vRealSize . vec ( ) . x , ( int ) w - > m_vRealSize . vec ( ) . y , w - > m_iWorkspaceID , ( w - > m_iWorkspaceID = = - 1 ? " " : g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ? g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) - > m_szName . c_str ( ) : std : : string ( " Invalid workspace " + std : : to_string ( w - > m_iWorkspaceID ) ) . c_str ( ) ) , ( int ) w - > m_bIsFloating , w - > m_iMonitorID , g_pXWaylandManager - > getAppIDClass ( w . get ( ) ) . c_str ( ) , g_pXWaylandManager - > getTitle ( w . get ( ) ) . c_str ( ) , w - > getPID ( ) , ( int ) w - > m_bIsX11 , ( int ) w - > m_bPinned , ( int ) w - > m_bIsFullscreen , ( w - > m_bIsFullscreen ? ( g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ? g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) - > m_efFullscreenMode : 0 ) : 0 ) ) ;
2022-09-25 20:07:48 +02:00
2022-07-12 19:57:33 +02:00
}
2022-06-27 13:17:11 +02:00
}
2022-03-20 16:51:14 +01:00
}
return result ;
}
2022-07-12 22:59:36 +02:00
std : : string workspacesRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-03-20 16:51:14 +01:00
std : : string result = " " ;
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
result + = " [ " ;
for ( auto & w : g_pCompositor - > m_vWorkspaces ) {
2022-09-04 18:32:03 +02:00
const auto PLASTW = w - > getLastFocusedWindow ( ) ;
2022-07-12 19:57:33 +02:00
result + = getFormat (
R " #({
" id " : % i ,
" name " : " %s " ,
" monitor " : " %s " ,
" windows " : % i ,
2022-09-04 18:32:03 +02:00
" hasfullscreen " : % s ,
2022-09-08 18:47:39 +02:00
" lastwindow " : " 0x%x " ,
2022-09-04 18:32:03 +02:00
" lastwindowtitle " : " %s "
2022-07-12 19:57:33 +02:00
} , ) # " ,
w - > m_iID ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( w - > m_szName ) . c_str ( ) ,
escapeJSONStrings ( g_pCompositor - > getMonitorFromID ( w - > m_iMonitorID ) - > szName ) . c_str ( ) ,
2022-07-12 19:57:33 +02:00
g_pCompositor - > getWindowsOnWorkspace ( w - > m_iID ) ,
2022-09-04 18:32:03 +02:00
( ( int ) w - > m_bHasFullscreenWindow = = 1 ? " true " : " false " ) ,
PLASTW ,
2022-09-05 21:32:37 +02:00
PLASTW ? escapeJSONStrings ( PLASTW - > m_szTitle ) . c_str ( ) : " "
2022-07-12 19:57:33 +02:00
) ;
}
// remove trailing comma
result . pop_back ( ) ;
result + = " ] " ;
} else {
for ( auto & w : g_pCompositor - > m_vWorkspaces ) {
2022-09-04 18:32:03 +02:00
const auto PLASTW = w - > getLastFocusedWindow ( ) ;
2022-09-08 18:47:39 +02:00
result + = getFormat ( " workspace ID %i (%s) on monitor %s: \n \t windows: %i \n \t hasfullscreen: %i \n \t lastwindow: 0x%x \n \t lastwindowtitle: %s \n \n " ,
2022-09-04 18:32:03 +02:00
w - > m_iID , w - > m_szName . c_str ( ) , g_pCompositor - > getMonitorFromID ( w - > m_iMonitorID ) - > szName . c_str ( ) , g_pCompositor - > getWindowsOnWorkspace ( w - > m_iID ) , ( int ) w - > m_bHasFullscreenWindow , PLASTW , PLASTW ? PLASTW - > m_szTitle . c_str ( ) : " " ) ;
2022-07-12 19:57:33 +02:00
}
2022-03-20 16:51:14 +01:00
}
return result ;
}
2022-07-12 22:59:36 +02:00
std : : string activeWindowRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-04-02 18:57:09 +02:00
const auto PWINDOW = g_pCompositor - > m_pLastWindow ;
2022-03-22 16:54:45 +01:00
if ( ! g_pCompositor - > windowValidMapped ( PWINDOW ) )
2022-08-06 21:36:28 +02:00
return format = = HyprCtl : : FORMAT_JSON ? " {} " : " Invalid " ;
2022-03-22 16:54:45 +01:00
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
return getFormat (
R " #({
" address " : " 0x%x " ,
" at " : [ % i , % i ] ,
" size " : [ % i , % i ] ,
" workspace " : {
" id " : % i ,
" name " : " %s "
} ,
2022-08-09 01:22:55 +02:00
" floating " : % s ,
2022-07-12 19:57:33 +02:00
" monitor " : % i ,
" class " : " %s " ,
" title " : " %s " ,
2022-07-26 18:25:08 +02:00
" pid " : % i ,
2022-08-09 01:22:55 +02:00
" xwayland " : % s
2022-07-12 19:57:33 +02:00
} ) # " ,
PWINDOW ,
( int ) PWINDOW - > m_vRealPosition . vec ( ) . x , ( int ) PWINDOW - > m_vRealPosition . vec ( ) . y ,
( int ) PWINDOW - > m_vRealSize . vec ( ) . x , ( int ) PWINDOW - > m_vRealSize . vec ( ) . y ,
2022-07-18 20:47:28 +02:00
PWINDOW - > m_iWorkspaceID , escapeJSONStrings ( PWINDOW - > m_iWorkspaceID = = - 1 ? " " : g_pCompositor - > getWorkspaceByID ( PWINDOW - > m_iWorkspaceID ) - > m_szName ) . c_str ( ) ,
2022-08-08 22:48:33 +02:00
( ( int ) PWINDOW - > m_bIsFloating = = 1 ? " true " : " false " ) ,
2022-07-12 19:57:33 +02:00
PWINDOW - > m_iMonitorID ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( g_pXWaylandManager - > getAppIDClass ( PWINDOW ) ) . c_str ( ) ,
escapeJSONStrings ( g_pXWaylandManager - > getTitle ( PWINDOW ) ) . c_str ( ) ,
2022-07-26 18:25:08 +02:00
PWINDOW - > getPID ( ) ,
2022-08-08 22:48:33 +02:00
( ( int ) PWINDOW - > m_bIsX11 = = 1 ? " true " : " false " )
2022-07-12 19:57:33 +02:00
) ;
} else {
2022-07-26 18:25:08 +02:00
return getFormat ( " Window %x -> %s: \n \t at: %i,%i \n \t size: %i,%i \n \t workspace: %i (%s) \n \t floating: %i \n \t monitor: %i \n \t class: %s \n \t title: %s \n \t pid: %i \n \t xwayland: %i \n \n " ,
PWINDOW , PWINDOW - > m_szTitle . c_str ( ) , ( int ) PWINDOW - > m_vRealPosition . vec ( ) . x , ( int ) PWINDOW - > m_vRealPosition . vec ( ) . y , ( int ) PWINDOW - > m_vRealSize . vec ( ) . x , ( int ) PWINDOW - > m_vRealSize . vec ( ) . y , PWINDOW - > m_iWorkspaceID , ( PWINDOW - > m_iWorkspaceID = = - 1 ? " " : g_pCompositor - > getWorkspaceByID ( PWINDOW - > m_iWorkspaceID ) - > m_szName . c_str ( ) ) , ( int ) PWINDOW - > m_bIsFloating , ( int ) PWINDOW - > m_iMonitorID , g_pXWaylandManager - > getAppIDClass ( PWINDOW ) . c_str ( ) , g_pXWaylandManager - > getTitle ( PWINDOW ) . c_str ( ) , PWINDOW - > getPID ( ) , ( int ) PWINDOW - > m_bIsX11 ) ;
2022-07-12 19:57:33 +02:00
}
2022-03-22 16:54:45 +01:00
}
2022-07-12 22:59:36 +02:00
std : : string layersRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-03-22 16:54:45 +01:00
std : : string result = " " ;
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
result + = " { \n " ;
for ( auto & mon : g_pCompositor - > m_vMonitors ) {
result + = getFormat (
R " #( " % s " : {
" levels " : {
) # " ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( mon - > szName ) . c_str ( )
2022-09-25 20:07:48 +02:00
) ;
2022-07-12 19:57:33 +02:00
int layerLevel = 0 ;
for ( auto & level : mon - > m_aLayerSurfaceLists ) {
result + = getFormat (
2022-09-25 20:07:48 +02:00
R " #(
2022-07-12 19:57:33 +02:00
" %i " : [
) # " ,
layerLevel
) ;
for ( auto & layer : level ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" x " : % i ,
" y " : % i ,
" w " : % i ,
" h " : % i ,
" namespace " : " %s "
} , ) # " ,
2022-07-23 15:48:08 +02:00
layer . get ( ) ,
2022-07-12 19:57:33 +02:00
layer - > geometry . x ,
layer - > geometry . y ,
layer - > geometry . width ,
layer - > geometry . height ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( layer - > szNamespace ) . c_str ( )
2022-07-12 19:57:33 +02:00
) ;
}
// remove trailing comma
result . pop_back ( ) ;
if ( level . size ( ) > 0 )
result + = " \n " ;
result + = " ], " ;
layerLevel + + ;
2022-03-22 16:54:45 +01:00
}
2022-07-12 19:57:33 +02:00
// remove trailing comma
result . pop_back ( ) ;
result + = " \n } \n }, " ;
}
// remove trailing comma
result . pop_back ( ) ;
result + = " \n } \n " ;
2022-09-25 20:07:48 +02:00
2022-07-12 19:57:33 +02:00
} else {
for ( auto & mon : g_pCompositor - > m_vMonitors ) {
result + = getFormat ( " Monitor %s: \n " , mon - > szName . c_str ( ) ) ;
int layerLevel = 0 ;
for ( auto & level : mon - > m_aLayerSurfaceLists ) {
result + = getFormat ( " \t Layer level %i: \n " , layerLevel ) ;
for ( auto & layer : level ) {
2022-07-23 15:48:08 +02:00
result + = getFormat ( " \t \t Layer %x: xywh: %i %i %i %i, namespace: %s \n " , layer . get ( ) , layer - > geometry . x , layer - > geometry . y , layer - > geometry . width , layer - > geometry . height , layer - > szNamespace . c_str ( ) ) ;
2022-07-12 19:57:33 +02:00
}
layerLevel + + ;
}
result + = " \n \n " ;
2022-03-22 16:54:45 +01:00
}
}
return result ;
}
2022-07-12 22:59:36 +02:00
std : : string devicesRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
2022-06-02 13:59:33 +02:00
std : : string result = " " ;
2022-07-12 22:59:36 +02:00
if ( format = = HyprCtl : : FORMAT_JSON ) {
2022-07-12 19:57:33 +02:00
result + = " { \n " ;
result + = " \" mice \" : [ \n " ;
for ( auto & m : g_pInputManager - > m_lMice ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
2022-09-12 17:09:04 +02:00
" name " : " %s " ,
" defaultSpeed " : % f
2022-07-12 19:57:33 +02:00
} , ) # " ,
& m ,
2022-09-12 17:09:04 +02:00
escapeJSONStrings ( m . mouse - > name ) . c_str ( ) ,
wlr_input_device_is_libinput ( m . mouse ) ? libinput_device_config_accel_get_default_speed ( ( libinput_device * ) wlr_libinput_get_device_handle ( m . mouse ) ) : 0.f
2022-07-12 19:57:33 +02:00
) ;
}
2022-06-02 13:59:33 +02:00
2022-07-12 19:57:33 +02:00
// remove trailing comma
result . pop_back ( ) ;
result + = " \n ], \n " ;
result + = " \" keyboards \" : [ \n " ;
for ( auto & k : g_pInputManager - > m_lKeyboards ) {
2022-08-16 16:10:20 +02:00
const auto KM = g_pInputManager - > getActiveLayoutForKeyboard ( & k ) ;
2022-07-12 19:57:33 +02:00
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" name " : " %s " ,
" rules " : " %s " ,
" model " : " %s " ,
" layout " : " %s " ,
" variant " : " %s " ,
2022-07-13 16:02:14 +02:00
" options " : " %s " ,
2022-08-18 17:34:01 +02:00
" active_keymap " : " %s " ,
" main " : % s
2022-07-12 19:57:33 +02:00
} , ) # " ,
& k ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( k . keyboard - > name ) . c_str ( ) ,
escapeJSONStrings ( k . currentRules . rules ) . c_str ( ) ,
escapeJSONStrings ( k . currentRules . model ) . c_str ( ) ,
escapeJSONStrings ( k . currentRules . layout ) . c_str ( ) ,
escapeJSONStrings ( k . currentRules . variant ) . c_str ( ) ,
escapeJSONStrings ( k . currentRules . options ) . c_str ( ) ,
2022-08-18 17:34:01 +02:00
escapeJSONStrings ( KM ) . c_str ( ) ,
2022-08-18 17:50:32 +02:00
( k . active ? " true " : " false " )
2022-07-12 19:57:33 +02:00
) ;
}
2022-06-02 13:59:33 +02:00
2022-07-12 19:57:33 +02:00
// remove trailing comma
result . pop_back ( ) ;
result + = " \n ], \n " ;
2022-06-02 13:59:33 +02:00
2022-07-12 19:57:33 +02:00
result + = " \" tablets \" : [ \n " ;
2022-06-02 13:59:33 +02:00
2022-07-12 19:57:33 +02:00
for ( auto & d : g_pInputManager - > m_lTabletPads ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" type " : " tabletPad " ,
" belongsTo " : {
" address " : " 0x%x " ,
" name " : " %s "
}
} , ) # " ,
& d ,
d . pTabletParent ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( d . pTabletParent ? d . pTabletParent - > wlrDevice ? d . pTabletParent - > wlrDevice - > name : " " : " " ) . c_str ( )
2022-07-12 19:57:33 +02:00
) ;
}
2022-06-09 19:25:26 +02:00
2022-07-12 19:57:33 +02:00
for ( auto & d : g_pInputManager - > m_lTablets ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" name " : " %s "
} , ) # " ,
& d ,
2022-07-18 20:47:28 +02:00
escapeJSONStrings ( d . wlrDevice ? d . wlrDevice - > name : " " ) . c_str ( )
2022-07-12 19:57:33 +02:00
) ;
}
2022-06-09 19:25:26 +02:00
2022-07-12 19:57:33 +02:00
for ( auto & d : g_pInputManager - > m_lTabletTools ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" type " : " tabletTool " ,
" belongsTo " : " 0x%x "
} , ) # " ,
& d ,
d . wlrTabletTool ? d . wlrTabletTool - > data : 0
) ;
}
2022-09-21 15:39:25 +02:00
// remove trailing comma
result . pop_back ( ) ;
result + = " \n ], \n " ;
result + = " \" touch \" : [ \n " ;
for ( auto & d : g_pInputManager - > m_lTouchDevices ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" name " : " %s "
} , ) # " ,
& d ,
d . pWlrDevice ? d . pWlrDevice - > name : " "
) ;
}
2022-10-04 21:07:21 +02:00
// remove trailing comma
if ( result [ result . size ( ) - 1 ] = = ' , ' )
result . pop_back ( ) ;
result + = " \n ], \n " ;
result + = " \" switches \" : [ \n " ;
for ( auto & d : g_pInputManager - > m_lSwitches ) {
result + = getFormat (
R " #( {
" address " : " 0x%x " ,
" name " : " %s "
} , ) # " ,
& d ,
d . pWlrDevice ? d . pWlrDevice - > name : " "
) ;
}
2022-07-12 19:57:33 +02:00
// remove trailing comma
if ( result [ result . size ( ) - 1 ] = = ' , ' )
result . pop_back ( ) ;
result + = " \n ] \n " ;
2022-06-09 19:25:26 +02:00
2022-07-12 19:57:33 +02:00
result + = " } \n " ;
} else {
result + = " mice: \n " ;
for ( auto & m : g_pInputManager - > m_lMice ) {
2022-09-12 17:09:04 +02:00
result + = getFormat ( " \t Mouse at %x: \n \t \t %s \n \t \t \t default speed: %f \n " , & m , m . mouse - > name , ( wlr_input_device_is_libinput ( m . mouse ) ? libinput_device_config_accel_get_default_speed ( ( libinput_device * ) wlr_libinput_get_device_handle ( m . mouse ) ) : 0.f ) ) ;
2022-07-12 19:57:33 +02:00
}
result + = " \n \n Keyboards: \n " ;
for ( auto & k : g_pInputManager - > m_lKeyboards ) {
2022-08-16 16:10:20 +02:00
const auto KM = g_pInputManager - > getActiveLayoutForKeyboard ( & k ) ;
2022-08-18 17:50:32 +02:00
result + = getFormat ( " \t Keyboard at %x: \n \t \t %s \n \t \t \t rules: r \" %s \" , m \" %s \" , l \" %s \" , v \" %s \" , o \" %s \" \n \t \t \t active keymap: %s \n \t \t \t main: %s \n " , & k , k . keyboard - > name , k . currentRules . rules . c_str ( ) , k . currentRules . model . c_str ( ) , k . currentRules . layout . c_str ( ) , k . currentRules . variant . c_str ( ) , k . currentRules . options . c_str ( ) , KM . c_str ( ) , ( k . active ? " yes " : " no " ) ) ;
2022-07-12 19:57:33 +02:00
}
result + = " \n \n Tablets: \n " ;
for ( auto & d : g_pInputManager - > m_lTabletPads ) {
result + = getFormat ( " \t Tablet Pad at %x (belongs to %x -> %s) \n " , & d , d . pTabletParent , d . pTabletParent ? d . pTabletParent - > wlrDevice ? d . pTabletParent - > wlrDevice - > name : " " : " " ) ;
}
for ( auto & d : g_pInputManager - > m_lTablets ) {
result + = getFormat ( " \t Tablet at %x: \n \t \t %s \n " , & d , d . wlrDevice ? d . wlrDevice - > name : " " ) ;
}
for ( auto & d : g_pInputManager - > m_lTabletTools ) {
result + = getFormat ( " \t Tablet Tool at %x (belongs to %x) \n " , & d , d . wlrTabletTool ? d . wlrTabletTool - > data : 0 ) ;
}
2022-09-21 15:39:25 +02:00
result + = " \n \n Touch: \n " ;
for ( auto & d : g_pInputManager - > m_lTouchDevices ) {
result + = getFormat ( " \t Touch Device at %x: \n \t \t %s \n " , & d , d . pWlrDevice ? d . pWlrDevice - > name : " " ) ;
}
2022-10-04 21:07:21 +02:00
result + = " \n \n Switches: \n " ;
for ( auto & d : g_pInputManager - > m_lSwitches ) {
result + = getFormat ( " \t Switch Device at %x: \n \t \t %s \n " , & d , d . pWlrDevice ? d . pWlrDevice - > name : " " ) ;
}
2022-06-09 19:25:26 +02:00
}
2022-06-02 13:59:33 +02:00
return result ;
}
2022-08-11 21:28:37 +02:00
std : : string versionRequest ( HyprCtl : : eHyprCtlOutputFormat format ) {
if ( format = = HyprCtl : : eHyprCtlOutputFormat : : FORMAT_NORMAL ) {
std : : string result = " Hyprland, built from branch " + std : : string ( GIT_BRANCH ) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " ( " + removeBeginEndSpacesTabs ( GIT_COMMIT_MESSAGE ) . c_str ( ) + " ). \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
# ifndef NDEBUG
2022-08-11 21:28:37 +02:00
result + = " debug \n " ;
2022-04-22 18:14:25 +02:00
# endif
2022-06-18 13:09:38 +02:00
# ifdef HYPRLAND_DEBUG
2022-08-11 21:28:37 +02: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 {
std : : string result = getFormat (
R " #({
" branch " : " %s " ,
" commit " : " %s " ,
" dirty " : % s
" commit_message " : " %s " ,
2022-08-11 21:29:31 +02:00
" flags " : [ ) # " , GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, " dirty " ) == 0 ? " true " : " false " ), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
2022-08-11 21:28:37 +02:00
# ifdef LEGACY_RENDERER
result + = " \" legacyrenderer \" , " ;
# endif
# ifndef NDEBUG
result + = " \" debug \" , " ;
# endif
# ifdef HYPRLAND_DEBUG
result + = " \" debug \" , " ;
# endif
# ifdef NO_XWAYLAND
result + = " \" no xwayland \" , " ;
# endif
if ( result [ result . length ( ) - 1 ] = = ' , ' )
result . pop_back ( ) ;
result + = " ] \n } " ;
return result ;
}
return " " ; // make the compiler happy
2022-04-22 18:14:25 +02:00
}
2022-04-21 16:11:29 +02:00
std : : string dispatchRequest ( std : : string in ) {
// get rid of the dispatch keyword
in = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
const auto DISPATCHSTR = in . substr ( 0 , in . find_first_of ( ' ' ) ) ;
const auto DISPATCHARG = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
const auto DISPATCHER = g_pKeybindManager - > m_mDispatchers . find ( DISPATCHSTR ) ;
if ( DISPATCHER = = g_pKeybindManager - > m_mDispatchers . end ( ) )
return " Invalid dispatcher " ;
DISPATCHER - > second ( DISPATCHARG ) ;
2022-04-21 21:48:37 +02:00
Debug : : log ( LOG , " Hyprctl: dispatcher %s : %s " , DISPATCHSTR . c_str ( ) , DISPATCHARG . c_str ( ) ) ;
2022-04-21 16:11:29 +02:00
return " ok " ;
}
2022-04-21 16:56:27 +02:00
std : : string dispatchKeyword ( std : : string in ) {
// get rid of the keyword keyword
in = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
const auto COMMAND = in . substr ( 0 , in . find_first_of ( ' ' ) ) ;
const auto VALUE = in . substr ( in . find_first_of ( ' ' ) + 1 ) ;
std : : string retval = g_pConfigManager - > parseKeyword ( COMMAND , VALUE , true ) ;
2022-04-21 21:36:45 +02:00
if ( COMMAND = = " monitor " )
g_pConfigManager - > m_bWantsMonitorReload = true ; // for monitor keywords
2022-04-21 17:36:28 +02:00
2022-08-20 18:57:30 +02:00
if ( COMMAND . contains ( " input " ) | | COMMAND . contains ( " device: " ) ) {
2022-04-22 14:11:52 +02:00
g_pInputManager - > setKeyboardLayout ( ) ; // update kb layout
2022-10-05 22:21:22 +02:00
g_pInputManager - > setPointerConfigs ( ) ; // update mouse cfgs
2022-08-20 18:57:30 +02:00
}
2022-04-22 14:11:52 +02:00
2022-07-16 22:44:29 +02:00
if ( COMMAND . contains ( " general:layout " ) )
g_pLayoutManager - > switchToLayout ( g_pConfigManager - > getString ( " general:layout " ) ) ; // update layout
2022-04-21 21:48:37 +02:00
Debug : : log ( LOG , " Hyprctl: keyword %s : %s " , COMMAND . c_str ( ) , VALUE . c_str ( ) ) ;
2022-09-25 20:07:48 +02:00
if ( retval = = " " )
2022-04-21 16:56:27 +02:00
return " ok " ;
return retval ;
}
2022-08-14 23:26:18 +02:00
std : : string reloadRequest ( 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 " ;
}
2022-06-27 13:42:20 +02:00
std : : string killRequest ( ) {
g_pInputManager - > setClickMode ( CLICKMODE_KILL ) ;
return " ok " ;
}
2022-07-10 15:41:26 +02:00
std : : string splashRequest ( ) {
return g_pCompositor - > m_szCurrentSplash ;
}
2022-04-29 19:44:09 +02:00
std : : string getReply ( std : : string ) ;
std : : string dispatchBatch ( std : : string request ) {
// split by ;
request = request . substr ( 9 ) ;
std : : string curitem = " " ;
std : : string reply = " " ;
auto nextItem = [ & ] ( ) {
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 = " " ;
}
curitem = removeBeginEndSpacesTabs ( curitem ) ;
} ;
nextItem ( ) ;
while ( curitem ! = " " ) {
reply + = getReply ( curitem ) ;
nextItem ( ) ;
}
return reply ;
}
2022-08-10 21:22:11 +02:00
std : : string dispatchSetCursor ( std : : string request ) {
std : : string curitem = " " ;
auto nextItem = [ & ] ( ) {
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 = " " ;
}
curitem = removeBeginEndSpacesTabs ( curitem ) ;
} ;
nextItem ( ) ;
nextItem ( ) ;
const auto THEME = curitem ;
nextItem ( ) ;
const auto SIZE = curitem ;
if ( ! isNumber ( SIZE ) ) {
return " size not int " ;
}
const auto SIZEINT = std : : stoi ( SIZE ) ;
if ( SIZEINT < 1 ) {
return " size must be positive " ;
}
wlr_xcursor_manager_destroy ( g_pCompositor - > m_sWLRXCursorMgr ) ;
g_pCompositor - > m_sWLRXCursorMgr = wlr_xcursor_manager_create ( THEME . c_str ( ) , SIZEINT ) ;
setenv ( " XCURSOR_SIZE " , SIZE . c_str ( ) , true ) ;
setenv ( " XCURSOR_THEME " , THEME . c_str ( ) , true ) ;
for ( auto & m : g_pCompositor - > m_vMonitors ) {
wlr_xcursor_manager_load ( g_pCompositor - > m_sWLRXCursorMgr , m - > scale ) ;
}
return " ok " ;
}
2022-08-11 21:16:38 +02:00
std : : string dispatchGetOption ( std : : string request , HyprCtl : : eHyprCtlOutputFormat format ) {
std : : string curitem = " " ;
auto nextItem = [ & ] ( ) {
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 = " " ;
}
curitem = removeBeginEndSpacesTabs ( curitem ) ;
} ;
nextItem ( ) ;
nextItem ( ) ;
const auto PCFGOPT = g_pConfigManager - > getConfigValuePtrSafe ( curitem ) ;
if ( ! PCFGOPT )
return " no such option " ;
if ( format = = HyprCtl : : eHyprCtlOutputFormat : : FORMAT_NORMAL )
return getFormat ( " option %s \n \t int: %i \n \t float: %f \n \t str: \" %s \" " , curitem . c_str ( ) , PCFGOPT - > intValue , PCFGOPT - > floatValue , PCFGOPT - > strValue . c_str ( ) ) ;
else {
return getFormat (
R " #(
{
" option " : " %s " ,
" int " : % i ,
" float " : % f ,
" str " : " %s "
}
) # " , curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str()
) ;
}
}
2022-04-29 19:44:09 +02:00
std : : string getReply ( std : : string request ) {
2022-07-12 22:59:36 +02:00
auto format = HyprCtl : : FORMAT_NORMAL ;
2022-07-13 00:34:28 +02:00
// process flags for non-batch requests
2022-07-14 11:43:15 +02:00
if ( ! request . contains ( " [[BATCH]] " ) & & request . contains ( " / " ) ) {
2022-07-13 15:48:47 +02:00
long unsigned int sepIndex = 0 ;
2022-07-13 00:34:28 +02:00
for ( const auto & c : request ) {
if ( c = = ' / ' ) { // stop at separator
break ;
}
sepIndex + + ;
2022-09-25 20:07:48 +02:00
2022-07-13 00:34:28 +02:00
if ( c = = ' j ' )
format = HyprCtl : : FORMAT_JSON ;
2022-07-12 22:59:36 +02:00
}
2022-07-13 00:34:28 +02: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 22:59:36 +02:00
}
2022-04-29 19:44:09 +02:00
if ( request = = " monitors " )
2022-07-12 22:59:36 +02:00
return monitorsRequest ( format ) ;
2022-04-29 19:44:09 +02:00
else if ( request = = " workspaces " )
2022-07-12 22:59:36 +02:00
return workspacesRequest ( format ) ;
2022-04-29 19:44:09 +02:00
else if ( request = = " clients " )
2022-07-12 22:59:36 +02:00
return clientsRequest ( format ) ;
2022-06-27 13:42:20 +02:00
else if ( request = = " kill " )
return killRequest ( ) ;
2022-04-29 19:44:09 +02:00
else if ( request = = " activewindow " )
2022-07-12 22:59:36 +02:00
return activeWindowRequest ( format ) ;
2022-04-29 19:44:09 +02:00
else if ( request = = " layers " )
2022-07-12 22:59:36 +02:00
return layersRequest ( format ) ;
2022-04-29 19:44:09 +02:00
else if ( request = = " version " )
2022-08-11 21:28:37 +02:00
return versionRequest ( format ) ;
2022-08-14 23:26:18 +02:00
else if ( request . find ( " reload " ) = = 0 )
return reloadRequest ( request ) ;
2022-06-02 13:59:33 +02:00
else if ( request = = " devices " )
2022-07-12 22:59:36 +02:00
return devicesRequest ( format ) ;
2022-07-10 15:41:26 +02:00
else if ( request = = " splash " )
return splashRequest ( ) ;
2022-04-29 19:44:09 +02:00
else if ( request . find ( " dispatch " ) = = 0 )
return dispatchRequest ( request ) ;
else if ( request . find ( " keyword " ) = = 0 )
return dispatchKeyword ( request ) ;
2022-08-10 21:22:11 +02:00
else if ( request . find ( " setcursor " ) = = 0 )
return dispatchSetCursor ( request ) ;
2022-08-11 21:16:38 +02:00
else if ( request . find ( " getoption " ) = = 0 )
return dispatchGetOption ( request , format ) ;
2022-04-29 19:44:09 +02:00
else if ( request . find ( " [[BATCH]] " ) = = 0 )
return dispatchBatch ( request ) ;
return " unknown request " ;
}
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 ;
sockaddr_in clientAddress ;
socklen_t clientSize = sizeof ( clientAddress ) ;
const auto ACCEPTEDCONNECTION = accept ( HyprCtl : : iSocketFD , ( sockaddr * ) & clientAddress , & clientSize ) ;
char readBuffer [ 1024 ] ;
auto messageSize = read ( ACCEPTEDCONNECTION , readBuffer , 1024 ) ;
readBuffer [ messageSize = = 1024 ? 1023 : messageSize ] = ' \0 ' ;
std : : string request ( readBuffer ) ;
2022-04-21 22:00:03 +02:00
std : : string reply = " " ;
try {
2022-04-29 19:44:09 +02:00
reply = getReply ( request ) ;
2022-04-21 22:00:03 +02:00
} catch ( std : : exception & e ) {
Debug : : log ( ERR , " Error in request: %s " , e . what ( ) ) ;
reply = " Err: " + std : : string ( e . what ( ) ) ;
}
2022-09-10 21:21:28 +02:00
write ( ACCEPTEDCONNECTION , reply . c_str ( ) , reply . length ( ) ) ;
2022-04-21 22:00:03 +02:00
2022-09-10 21:21:28 +02:00
close ( ACCEPTEDCONNECTION ) ;
2022-08-03 17:12:38 +02:00
if ( g_pConfigManager - > m_bWantsMonitorReload ) {
2022-08-03 21:19:12 +02:00
g_pConfigManager - > ensureDPMS ( ) ;
2022-08-03 17:12:38 +02:00
}
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
}
2022-03-21 18:29:41 +01:00
void HyprCtl : : startHyprCtlSocket ( ) {
2022-03-20 16:51:14 +01:00
2022-09-10 21:21:28 +02:00
iSocketFD = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
if ( iSocketFD < 0 ) {
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
2022-09-10 21:21:28 +02:00
std : : string socketPath = " /tmp/hypr/ " + g_pCompositor - > m_szInstanceSignature + " /.socket.sock " ;
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
strcpy ( SERVERADDRESS . sun_path , socketPath . c_str ( ) ) ;
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
bind ( iSocketFD , ( sockaddr * ) & SERVERADDRESS , SUN_LEN ( & SERVERADDRESS ) ) ;
2022-03-21 18:29:41 +01:00
2022-09-10 21:21:28 +02:00
// 10 max queued.
listen ( iSocketFD , 10 ) ;
2022-03-22 16:54:45 +01:00
2022-09-10 21:21:28 +02:00
Debug : : log ( LOG , " Hypr socket started at %s " , socketPath . c_str ( ) ) ;
2022-08-28 11:19:08 +02:00
2022-09-10 21:21:28 +02:00
wl_event_loop_add_fd ( g_pCompositor - > m_sWLEventLoop , iSocketFD , WL_EVENT_READABLE , hyprCtlFDTick , nullptr ) ;
2022-08-05 01:25:56 +02:00
}