@@ -89,6 +89,8 @@ struct AppSettings {
8989 analytics_enabled : bool ,
9090 #[ serde( default ) ]
9191 hide_icon_on_close : bool ,
92+ #[ serde( default ) ]
93+ hide_status_bar : bool ,
9294}
9395
9496#[ derive( Serialize , Deserialize , Clone ) ]
@@ -177,6 +179,7 @@ impl Default for AppSettings {
177179 autostart : false , // default to disabled
178180 analytics_enabled : true , // default to enabled
179181 hide_icon_on_close : false , // default to disabled
182+ hide_status_bar : false , // default to disabled
180183 }
181184 }
182185}
@@ -949,7 +952,8 @@ pub fn run() {
949952 add_session_tag,
950953 write_excel_file,
951954 start_oauth_server,
952- set_dock_visibility
955+ set_dock_visibility,
956+ set_status_bar_visibility
953957 ] )
954958 . setup ( |app| {
955959 // Track app started event (if enabled)
@@ -1373,3 +1377,184 @@ fn set_dock_visibility_native(visible: bool) {
13731377 }
13741378 }
13751379}
1380+
1381+ // Status bar visibility management using Carbon APIs
1382+ //
1383+ // Implementation Notes:
1384+ // This feature uses Apple's Carbon SetSystemUIMode API, which is a pure C function
1385+ // from the ApplicationServices framework. This approach is much safer than using
1386+ // Objective-C APIs because:
1387+ //
1388+ // 1. No foreign exceptions: C APIs return error codes instead of throwing exceptions
1389+ // 2. Direct system integration: Carbon APIs are lower-level and more stable
1390+ // 3. Robust fallback system: Multiple approaches with retry mechanisms
1391+ // 4. Comprehensive error handling: Detailed OSStatus code interpretation
1392+ //
1393+ // The implementation uses:
1394+ // - Primary: SetSystemUIMode with K_UI_MODE_CONTENT_SUPPRESSED (hides menu bar, keeps dock)
1395+ // - Fallback 1: Retry with delay for transient errors
1396+ // - Fallback 2: Conservative two-step approach for hiding
1397+ // - Detailed error reporting with manual recovery instructions
1398+ #[ tauri:: command]
1399+ async fn set_status_bar_visibility ( _app : AppHandle , visible : bool ) -> Result < ( ) , String > {
1400+ #[ cfg( target_os = "macos" ) ]
1401+ {
1402+ match set_system_ui_mode_safe ( visible) {
1403+ Ok ( _) => {
1404+ println ! ( "✅ Status bar visibility successfully set to: {}" , if visible { "visible" } else { "hidden" } ) ;
1405+ Ok ( ( ) )
1406+ } ,
1407+ Err ( e) => {
1408+ eprintln ! ( "❌ Failed to set status bar visibility: {}" , e) ;
1409+ Err ( format ! ( "Failed to set status bar visibility: {}" , e) )
1410+ }
1411+ }
1412+ }
1413+
1414+ #[ cfg( not( target_os = "macos" ) ) ]
1415+ {
1416+ return Err ( "Status bar visibility is only supported on macOS" . to_string ( ) ) ;
1417+ }
1418+ }
1419+
1420+ #[ cfg( target_os = "macos" ) ]
1421+ fn set_system_ui_mode_safe ( visible : bool ) -> Result < ( ) , String > {
1422+ use libc:: { c_int, c_uint} ;
1423+ use std:: thread;
1424+ use std:: time:: Duration ;
1425+
1426+ // Carbon SetSystemUIMode constants
1427+ const K_UI_MODE_NORMAL : c_uint = 0 ; // Normal mode - menu bar visible
1428+ const K_UI_MODE_CONTENT_SUPPRESSED : c_uint = 1 ; // Menu bar hidden, dock visible
1429+ #[ allow( dead_code) ]
1430+ const K_UI_MODE_CONTENT_HIDDEN : c_uint = 2 ; // Menu bar hidden, dock auto-hide
1431+ #[ allow( dead_code) ]
1432+ const K_UI_MODE_ALL_HIDDEN : c_uint = 3 ; // Everything hidden
1433+
1434+ // OSStatus codes
1435+ const NO_ERR : c_int = 0 ;
1436+ const PARAM_ERR : c_int = -50 ;
1437+ const MEM_FULL_ERR : c_int = -108 ;
1438+
1439+ // SystemUIMode and SystemUIOptions are both UInt32 (c_uint)
1440+ type SystemUIMode = c_uint ;
1441+ type SystemUIOptions = c_uint ;
1442+ type OSStatus = c_int ;
1443+
1444+ // External declaration for Carbon SetSystemUIMode function
1445+ // This is a C function from ApplicationServices framework
1446+ extern "C" {
1447+ fn SetSystemUIMode ( inMode : SystemUIMode , inOptions : SystemUIOptions ) -> OSStatus ;
1448+ }
1449+
1450+ // Try the primary approach with Carbon SetSystemUIMode
1451+ let primary_result = unsafe {
1452+ let mode = if visible {
1453+ K_UI_MODE_NORMAL // Show menu bar
1454+ } else {
1455+ K_UI_MODE_CONTENT_SUPPRESSED // Hide menu bar but keep dock visible
1456+ } ;
1457+
1458+ let options: SystemUIOptions = 0 ; // No special options
1459+
1460+ println ! ( "🔧 Carbon API: Setting SystemUIMode to {} ({})" ,
1461+ mode, if visible { "normal/visible" } else { "content suppressed/hidden" } ) ;
1462+
1463+ // Call the Carbon function - this is a pure C API call
1464+ let result: OSStatus = SetSystemUIMode ( mode, options) ;
1465+
1466+ if result == NO_ERR {
1467+ println ! ( "✅ Carbon API: SetSystemUIMode succeeded" ) ;
1468+ Ok ( ( ) )
1469+ } else {
1470+ let error_msg = format ! ( "Carbon API failed with OSStatus: {} ({})" ,
1471+ result, get_osstatus_description( result) ) ;
1472+ eprintln ! ( "❌ Carbon API: {}" , error_msg) ;
1473+ Err ( ( result, error_msg) )
1474+ }
1475+ } ;
1476+
1477+ // If primary approach succeeded, return success
1478+ if primary_result. is_ok ( ) {
1479+ return Ok ( ( ) ) ;
1480+ }
1481+
1482+ // If primary approach failed, try fallback methods
1483+ let ( status_code, error_msg) = primary_result. unwrap_err ( ) ;
1484+
1485+ eprintln ! ( "🔄 Primary method failed, attempting fallback approaches..." ) ;
1486+
1487+ // Fallback 1: Try with a small delay and retry
1488+ if status_code == PARAM_ERR || status_code == MEM_FULL_ERR {
1489+ println ! ( "🔄 Fallback 1: Retrying after brief delay..." ) ;
1490+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
1491+
1492+ let retry_result = unsafe {
1493+ let mode = if visible { K_UI_MODE_NORMAL } else { K_UI_MODE_CONTENT_SUPPRESSED } ;
1494+ let result: OSStatus = SetSystemUIMode ( mode, 0 ) ;
1495+
1496+ if result == NO_ERR {
1497+ println ! ( "✅ Fallback 1: Retry succeeded" ) ;
1498+ Ok ( ( ) )
1499+ } else {
1500+ Err ( format ! ( "Retry failed with OSStatus: {}" , result) )
1501+ }
1502+ } ;
1503+
1504+ if retry_result. is_ok ( ) {
1505+ return Ok ( ( ) ) ;
1506+ }
1507+ }
1508+
1509+ // Fallback 2: For hiding, try a more conservative approach
1510+ if !visible {
1511+ println ! ( "🔄 Fallback 2: Trying conservative hide approach..." ) ;
1512+
1513+ let conservative_result = unsafe {
1514+ // Try normal mode first, then content suppressed
1515+ SetSystemUIMode ( K_UI_MODE_NORMAL , 0 ) ;
1516+ thread:: sleep ( Duration :: from_millis ( 50 ) ) ;
1517+ let result: OSStatus = SetSystemUIMode ( K_UI_MODE_CONTENT_SUPPRESSED , 0 ) ;
1518+
1519+ if result == NO_ERR {
1520+ println ! ( "✅ Fallback 2: Conservative approach succeeded" ) ;
1521+ Ok ( ( ) )
1522+ } else {
1523+ Err ( format ! ( "Conservative approach failed with OSStatus: {}" , result) )
1524+ }
1525+ } ;
1526+
1527+ if conservative_result. is_ok ( ) {
1528+ return Ok ( ( ) ) ;
1529+ }
1530+ }
1531+
1532+ // All methods failed - provide detailed error information
1533+ let detailed_error = format ! (
1534+ "All status bar visibility methods failed. Primary error: {}. \
1535+ This might be due to system restrictions or macOS version compatibility. \
1536+ You can manually hide the menu bar using System Preferences > Dock & Menu Bar > 'Automatically hide and show the menu bar'.",
1537+ error_msg
1538+ ) ;
1539+
1540+ eprintln ! ( "❌ {}" , detailed_error) ;
1541+ Err ( detailed_error)
1542+ }
1543+
1544+ #[ cfg( target_os = "macos" ) ]
1545+ fn get_osstatus_description ( status : libc:: c_int ) -> & ' static str {
1546+ match status {
1547+ 0 => "No error - Success" ,
1548+ -50 => "Parameter error - Invalid parameters passed to function" ,
1549+ -108 => "Memory full error - Insufficient memory available" ,
1550+ -25291 => "Invalid system UI mode - The specified UI mode is not valid" ,
1551+ -25292 => "Operation not supported in current mode - Cannot change UI mode in current state" ,
1552+ -25293 => "System UI server not available - UI server is not responding" ,
1553+ -25294 => "System UI mode locked - UI mode changes are currently locked" ,
1554+ -128 => "User canceled - Operation was canceled by user" ,
1555+ -43 => "File not found - Required system component not found" ,
1556+ -5000 => "System policy error - Operation blocked by system policy" ,
1557+ -1 => "General error - Unspecified error occurred" ,
1558+ _ => "Unknown error - Undocumented error code"
1559+ }
1560+ }
0 commit comments