apognu / tuigreet

Graphical console greeter for greetd
GNU General Public License v3.0
992 stars 45 forks source link

X11 WM command fails due to X server never starting #92

Closed stevensonmt closed 1 year ago

stevensonmt commented 1 year ago

This is similar to what was discussed in https://github.com/apognu/tuigreet/issues/15. Basically if my command is startx and the last line of my .xinitrc is the window manager exec (leftwm in my case) then it works, but if my command is directly leftwm it fails. What is the expected behavior/command for launching an X11 WM?

Looking at qtgreet it seems that this is the bit that creates an X11 session correctly:

bool GreetdLogin::startSession( QString baseCmd, QString type ) {
    /** Get the log name */
    QString logName = logPath + "/session/QtGreet-" + QDateTime::currentDateTime().toString( "ddMMyyyy-hhmmss" ) + ".log";

    QString cmd;

    if ( type == "wayland" ) {
        cmd = baseCmd + " > " + logName + " 2>&1";
    }

    else if ( type == "X11" ) {
        cmd = getX11Session( baseCmd ) + " > " + logName + " 2>&1";
    }

    else {
        cmd = baseCmd;
    }

    /** Send the start_session request */
    Response resp = startSession( cmd, prepareEnv() );

    if ( resp.responseType() == Response::Success ) {
        return true;
    }

    qDebug() << "Failed to launch the session:" << baseCmd;
    mErrorMsg = resp.errorMessage();
    resp      = cancelSession();

    if ( resp.responseType() != Response::Success ) {
        mErrorMsg += "\nError while handling the previous error. Abort.";
    }

    qDebug() << mErrorMsg;

    return false;
}

and

QString GreetdLogin::getX11Session( QString base ) {
    QString xinit( "xinit %1 -- %2 :%3 vt%4 -keeptty -noreset -novtswitch -auth %5/Xauth.%6" );

    /* Arg2: Get the display */
    int display;

    for ( display = 0; display < 64; display++ ) {
        QString x1 = QString( tmpPath + "/.X%1-lock" ).arg( display );
        QString x2 = QString( tmpPath + "/.X11-unix/X%1" ).arg( display );

        if ( QFile::exists( x1 ) or QFile::exists( x2 ) ) {
            continue;
        }

        else {
            break;
        }
    }

    /* Arg4: Random strings for server auth file */
    QString hash = QCryptographicHash::hash( QDateTime::currentDateTime().toString().toUtf8(), QCryptographicHash::Md5 ).toHex().left( 10 );

    return xinit.arg( base ).arg( xrcPath ).arg( display ).arg( vtNum ).arg( tmpPath ).arg( hash );
}

I will take a look at tuigreet's src to see if this can be added.

stevensonmt commented 1 year ago

So I think in info.rs when getting sessions, X11 desktop entries need to be handled differently from Wayland entries. I think something like

fn load_desktop_file<P>(path: P) -> Result<(String, String), Box<dyn Error>>
where
  P: AsRef<Path>,
{
  let desktop = Ini::load_from_file(path)?;
  let section = desktop.section(Some("Desktop Entry")).ok_or("no Desktop Entry section in desktop file")?;

  let name = section.get("Name").ok_or("no Name property in desktop file")?;
  let exec = 
        match (section.get("Exec"), path.parent) {
            (Ok(exec), Some(Path::new(X_SESSIONS))) => 
                format!("xinit ${exec}")
           (Ok(exec), _) => exec.to_string()
           _ => format!("no Exec property in desktop file")
        };

  Ok((name.to_string(), exec))
}

I don't think specifying all those other xinit parameters the way qtgreeter does is necessary in most cases.