private void ShutdownCancelledHandler()
 {
     if (_saveYourselfPhase)
     {
         SMLib.SmcSaveYourselfDone(_currentSmcConn, true);
     }
     _saveYourselfPhase = false;
 }
        internal X11PlatformLifetimeEvents(AvaloniaX11Platform platform)
        {
            _platform = platform;

            if (ICELib.IceAddConnectionWatch(
                    Marshal.GetFunctionPointerForDelegate(s_iceWatchProcDelegate),
                    IntPtr.Zero) == 0)
            {
                Logger.TryGet(LogEventLevel.Warning, LogArea.X11Platform)?.Log(this,
                                                                               "SMLib was unable to add an ICE connection watcher.");
                return;
            }

            byte[] errorBuf    = new byte[255];
            IntPtr clientIdRet = IntPtr.Zero;
            var    smcConn     = SMLib.SmcOpenConnection(null,
                                                         IntPtr.Zero, 1, 0,
                                                         SmcSaveYourselfProcMask |
                                                         SmcSaveCompleteProcMask |
                                                         SmcShutdownCancelledProcMask |
                                                         SmcDieProcMask,
                                                         ref s_callbacks,
                                                         null,
                                                         ref clientIdRet,
                                                         errorBuf.Length,
                                                         errorBuf);

            if (smcConn == IntPtr.Zero)
            {
                Logger.TryGet(LogEventLevel.Warning, LogArea.X11Platform)?.Log(this,
                                                                               $"SMLib/ICELib reported a new error: {Encoding.ASCII.GetString(errorBuf)}");
                return;
            }

            if (!s_nativeToManagedMapper.TryAdd(smcConn, this))
            {
                Logger.TryGet(LogEventLevel.Warning, LogArea.X11Platform)?.Log(this,
                                                                               "SMLib was unable to add this instance to the native to managed map.");
                return;
            }

            _ = SMLib.SmcSetErrorHandler(Marshal.GetFunctionPointerForDelegate(s_smcErrorHandlerDelegate));
            _ = ICELib.IceSetErrorHandler(Marshal.GetFunctionPointerForDelegate(s_iceErrorHandlerDelegate));
            _ = ICELib.IceSetIOErrorHandler(Marshal.GetFunctionPointerForDelegate(s_iceIoErrorHandlerDelegate));

            _currentSmcConn = smcConn;
            _currentIceConn = SMLib.SmcGetIceConnection(smcConn);

            Task.Run(() =>
            {
                var token = _cancellationTokenSource.Token;
                while (!token.IsCancellationRequested)
                {
                    HandleRequests();
                }
            }, _cancellationTokenSource.Token);
        }
        public void Dispose()
        {
            if (_currentSmcConn == IntPtr.Zero)
            {
                return;
            }

            s_nativeToManagedMapper.TryRemove(_currentSmcConn, out _);

            _ = SMLib.SmcCloseConnection(_currentSmcConn, 1,
                                         new[] { $"{nameof(X11PlatformLifetimeEvents)} was disposed in managed code." });
        }
        private void ActualInteractHandler(IntPtr smcConn)
        {
            var e = new ShutdownRequestedEventArgs();

            if (_platform.Options?.EnableSessionManagement ?? false)
            {
                ShutdownRequested?.Invoke(this, e);
            }

            SMLib.SmcInteractDone(smcConn, e.Cancel);

            if (e.Cancel)
            {
                return;
            }

            _saveYourselfPhase = false;

            SMLib.SmcSaveYourselfDone(smcConn, true);
        }
        private void SaveYourselfHandler(IntPtr smcConn, IntPtr clientData, bool shutdown, bool fast)
        {
            if (_saveYourselfPhase)
            {
                SMLib.SmcSaveYourselfDone(smcConn, true);
            }

            _saveYourselfPhase = true;

            if (shutdown && !fast)
            {
                var _ = SMLib.SmcInteractRequest(smcConn, SMLib.SmDialogValue.SmDialogError,
                                                 Marshal.GetFunctionPointerForDelegate(s_smcInteractDelegate),
                                                 clientData);
            }
            else
            {
                SMLib.SmcSaveYourselfDone(smcConn, true);
                _saveYourselfPhase = false;
            }
        }