mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-09-22 13:01:05 +03:00
319 lines
11 KiB
C++
319 lines
11 KiB
C++
#include <args/args.hxx>
|
|
#include <eepp/ee.hpp>
|
|
#include <eterm/terminal/terminaldisplay.hpp>
|
|
#include <iostream>
|
|
|
|
EE::Window::Window* win = NULL;
|
|
std::shared_ptr<TerminalDisplay> terminal = nullptr;
|
|
Clock lastRender;
|
|
Clock secondsCounter;
|
|
Time frameTime{ Time::Zero };
|
|
bool benchmarkMode{ false };
|
|
std::string windowStringData;
|
|
std::map<std::string, TerminalColorScheme> terminalColorSchemes;
|
|
|
|
void loadColorSchemes( const std::string& resPath ) {
|
|
auto configPath = Sys::getConfigPath( "eterm" );
|
|
auto colorSchemes =
|
|
TerminalColorScheme::loadFromFile( resPath + "colorschemes/terminalcolorschemes.conf" );
|
|
auto colorSchemesPath = configPath + FileSystem::getOSSlash() + "colorschemes";
|
|
if ( FileSystem::isDirectory( colorSchemesPath ) ) {
|
|
auto colorSchemesFiles = FileSystem::filesGetInPath( colorSchemesPath );
|
|
for ( auto& file : colorSchemesFiles ) {
|
|
auto colorSchemesInFile = TerminalColorScheme::loadFromFile( file );
|
|
std::copy( colorSchemesInFile.begin(), colorSchemesInFile.end(),
|
|
std::back_inserter( colorSchemes ) );
|
|
}
|
|
}
|
|
for ( auto colorScheme : colorSchemes )
|
|
terminalColorSchemes.insert( { colorScheme.getName(), colorScheme } );
|
|
}
|
|
|
|
void inputCallback( InputEvent* event ) {
|
|
if ( !terminal || event->Type == InputEvent::EventsSent )
|
|
return;
|
|
|
|
switch ( event->Type ) {
|
|
case InputEvent::MouseMotion: {
|
|
terminal->onMouseMove( win->getInput()->getMousePos(),
|
|
win->getInput()->getPressTrigger() );
|
|
break;
|
|
}
|
|
case InputEvent::MouseButtonDown: {
|
|
terminal->onMouseDown( win->getInput()->getMousePos(),
|
|
win->getInput()->getPressTrigger() );
|
|
#if EE_PLATFORM == EE_PLATFORM_ANDROID
|
|
win->startTextInput();
|
|
#endif
|
|
break;
|
|
}
|
|
case InputEvent::MouseButtonUp: {
|
|
terminal->onMouseUp( win->getInput()->getMousePos(),
|
|
win->getInput()->getReleaseTrigger() );
|
|
|
|
if ( win->getInput()->getDoubleClickTrigger() ) {
|
|
terminal->onMouseDoubleClick( win->getInput()->getMousePos(),
|
|
win->getInput()->getDoubleClickTrigger() );
|
|
}
|
|
|
|
break;
|
|
}
|
|
case InputEvent::Window: {
|
|
switch ( event->window.type ) {
|
|
case InputEvent::WindowKeyboardFocusLost:
|
|
case InputEvent::WindowKeyboardFocusGain: {
|
|
terminal->setFocus( win->hasFocus() );
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case InputEvent::KeyUp: {
|
|
break;
|
|
}
|
|
case InputEvent::KeyDown: {
|
|
terminal->onKeyDown( event->key.keysym.sym, event->key.keysym.unicode,
|
|
event->key.keysym.mod, event->key.keysym.scancode );
|
|
#if EE_PLATFORM == EE_PLATFORM_ANDROID
|
|
if ( event->key.keysym.sym == KEY_RETURN ||
|
|
event->key.keysym.scancode == SCANCODE_RETURN ) {
|
|
win->startTextInput();
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
case InputEvent::TextInput: {
|
|
terminal->onTextInput( event->text.text );
|
|
break;
|
|
}
|
|
case InputEvent::VideoExpose:
|
|
terminal->setFocus( win->hasFocus() );
|
|
terminal->invalidate();
|
|
break;
|
|
case InputEvent::VideoResize: {
|
|
terminal->setPosition( { 0, 0 } );
|
|
terminal->setSize( win->getSize().asFloat() );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
|
#ifdef EE_DEBUG
|
|
Log::instance()->setLogToStdOut( true );
|
|
Log::instance()->setLiveWrite( true );
|
|
#endif
|
|
args::ArgumentParser parser( "eterm" );
|
|
args::HelpFlag help( parser, "help", "Display this help menu", { 'h', "help" } );
|
|
args::ValueFlag<std::string> shell( parser, "shell", "Shell name or path", { 's', "shell" },
|
|
"" );
|
|
args::ValueFlag<std::string> shellArgs( parser, "shell-args", "Shell command line arguments",
|
|
{ "shell-args" }, "" );
|
|
args::ValueFlag<size_t> historySize( parser, "scrollback", "Maximum history size (lines)",
|
|
{ 'l', "scrollback" }, 10000 );
|
|
args::Flag fb( parser, "framebuffer", "Use frame buffer (more memory usage, less CPU usage)",
|
|
{ "fb", "framebuffer" } );
|
|
args::ValueFlag<std::string> fontPath( parser, "fontpath", "Font path", { 'f', "font" } );
|
|
args::ValueFlag<std::string> fallbackFontPathF( parser, "fallback-fontpath",
|
|
"Fallback Font path", { "fallback-font" } );
|
|
args::ValueFlag<Float> fontSize( parser, "fontsize", "Font size (in dp)", { "fontsize" }, 11 );
|
|
args::ValueFlag<Float> width( parser, "winwidth", "Window width (in dp)", { "width" }, 1280 );
|
|
args::ValueFlag<Float> height( parser, "winheight", "Window height (in dp)", { "height" },
|
|
720 );
|
|
args::ValueFlag<Float> pixelDenstiyConf( parser, "pixel-density",
|
|
"Set default application pixel density",
|
|
{ 'd', "pixel-density" } );
|
|
args::Positional<std::string> wd( parser, "wording-dir", "Working Directory / executable" );
|
|
args::Flag closeOnExit( parser, "close-on-exit",
|
|
"close the application when the executable exits", { 'c', "close" } );
|
|
args::ValueFlag<std::string> executeInShell(
|
|
parser, "execute-in-shell", "execute program in shell", { 'e', "execute" }, "" );
|
|
args::Flag vsync( parser, "vsync", "Enable vsync", { "vsync" } );
|
|
args::ValueFlag<std::string> colorScheme( parser, "color-scheme", "Load color scheme",
|
|
{ "color-scheme" }, "" );
|
|
args::Flag listColorSchemes( parser, "color-schemes", "Lists color schemes",
|
|
{ "list-color-schemes" } );
|
|
args::ValueFlag<Uint32> maxFPS( parser, "max-fps",
|
|
"Maximum rendering frames per second of the terminal. Default "
|
|
"value will be the refresh rate of the screen.",
|
|
{ "max-fps" }, 0 );
|
|
args::Flag benchmarkModeFlag(
|
|
parser, "benchmark-mode",
|
|
"Render as much as possible to measure the rendering performance.", { "benchmark-mode" } );
|
|
|
|
try {
|
|
parser.ParseCLI( argc, argv );
|
|
} catch ( const args::Help& ) {
|
|
std::cout << parser;
|
|
return EXIT_SUCCESS;
|
|
} catch ( const args::ParseError& e ) {
|
|
std::cerr << e.what() << std::endl;
|
|
std::cerr << parser;
|
|
return EXIT_FAILURE;
|
|
} catch ( args::ValidationError& e ) {
|
|
std::cerr << e.what() << std::endl;
|
|
std::cerr << parser;
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
DisplayManager* displayManager = Engine::instance()->getDisplayManager();
|
|
Display* currentDisplay = displayManager->getDisplayIndex( 0 );
|
|
|
|
std::string resPath = Sys::getProcessPath();
|
|
#if EE_PLATFORM == EE_PLATFORM_MACOS
|
|
if ( String::contains( resPath, "ecode.app" ) ) {
|
|
resPath = FileSystem::getCurrentWorkingDirectory();
|
|
FileSystem::dirAddSlashAtEnd( resPath );
|
|
}
|
|
#elif EE_PLATFORM == EE_PLATFORM_LINUX
|
|
if ( String::contains( resPath, ".mount_" ) ) {
|
|
resPath = FileSystem::getCurrentWorkingDirectory();
|
|
FileSystem::dirAddSlashAtEnd( resPath );
|
|
}
|
|
#elif EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
|
resPath += "eterm/";
|
|
#endif
|
|
resPath += "assets";
|
|
FileSystem::dirAddSlashAtEnd( resPath );
|
|
|
|
if ( listColorSchemes.Get() || colorScheme )
|
|
loadColorSchemes( resPath );
|
|
|
|
if ( listColorSchemes.Get() ) {
|
|
std::cout << "Color schemes:\n";
|
|
for ( const auto& tcs : terminalColorSchemes )
|
|
std::cout << "\t" << tcs.first << "\n";
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
displayManager->enableScreenSaver();
|
|
displayManager->enableMouseFocusClickThrough();
|
|
displayManager->disableBypassCompositor();
|
|
|
|
Sizei winSize( width.Get(), height.Get() );
|
|
win = Engine::instance()->createWindow(
|
|
WindowSettings( winSize.getWidth(), winSize.getHeight(), "eterm", WindowStyle::Default,
|
|
WindowBackend::Default, 32, resPath + "icon/eterm.png",
|
|
pixelDenstiyConf ? pixelDenstiyConf.Get()
|
|
: currentDisplay->getPixelDensity() ),
|
|
ContextSettings( vsync.Get() ) );
|
|
|
|
if ( win->isOpen() ) {
|
|
win->setClearColor( RGB( 0, 0, 0 ) );
|
|
|
|
benchmarkMode = benchmarkModeFlag.Get();
|
|
|
|
FontTrueType* fontMono = nullptr;
|
|
if ( fontPath && FileSystem::fileExists( fontPath.Get() ) ) {
|
|
FileInfo file( fontPath.Get() );
|
|
fontMono = FontTrueType::New( "monospace" );
|
|
if ( fontMono->loadFromFile( file.getFilepath() ) ) {
|
|
FontFamily::loadFromRegular( fontMono );
|
|
} else {
|
|
fontMono = nullptr;
|
|
}
|
|
}
|
|
if ( fontMono == nullptr ) {
|
|
fontMono = FontTrueType::New( "monospace" );
|
|
fontMono->loadFromFile( resPath + "fonts/DejaVuSansMonoNerdFontComplete.ttf" );
|
|
FontFamily::loadFromRegular( fontMono, "DejaVuSansMono" );
|
|
}
|
|
|
|
if ( FileSystem::fileExists( resPath + "fonts/NotoColorEmoji.ttf" ) ) {
|
|
FontTrueType::New( "emoji-color" )
|
|
->loadFromFile( resPath + "fonts/NotoColorEmoji.ttf" );
|
|
} else if ( FileSystem::fileExists( resPath + "fonts/NotoEmoji-Regular.ttf" ) ) {
|
|
FontTrueType::New( "emoji-font" )
|
|
->loadFromFile( resPath + "fonts/NotoEmoji-Regular.ttf" );
|
|
}
|
|
|
|
std::string fallbackFontPath( fallbackFontPathF
|
|
? fallbackFontPathF.Get()
|
|
: resPath + "fonts/DroidSansFallbackFull.ttf" );
|
|
if ( FileSystem::fileExists( fallbackFontPath ) ) {
|
|
FontTrueType* fallbackFont = FontTrueType::New( "fallback-font" );
|
|
if ( fallbackFont->loadFromFile( fallbackFontPath ) )
|
|
FontManager::instance()->addFallbackFont( fallbackFont );
|
|
}
|
|
|
|
Float realMaxFPS = maxFPS.Get() ? maxFPS.Get() : currentDisplay->getRefreshRate();
|
|
frameTime = benchmarkMode ? Time::Zero : Milliseconds( 1000.f / realMaxFPS );
|
|
|
|
FileInfo file( wd ? wd.Get() : FileSystem::getCurrentWorkingDirectory() );
|
|
terminal = TerminalDisplay::create(
|
|
win, fontMono, PixelDensity::dpToPx( fontSize.Get() ), win->getSize().asFloat(),
|
|
file.isRegularFile() && file.isExecutable() ? file.getFilepath() : shell.Get(),
|
|
shellArgs ? String::split( shellArgs.Get() ) : std::vector<std::string>(),
|
|
file.getDirectoryPath(), historySize.Get(), nullptr, fb.Get(),
|
|
!( file.isRegularFile() && file.isExecutable() ) );
|
|
|
|
if ( terminal->getTerminal() == nullptr ) {
|
|
win->close();
|
|
win->showMessageBox( EE::Window::Window::MessageBoxType::Error, "eterm",
|
|
"Operating System not supported." );
|
|
terminal.reset();
|
|
Engine::destroySingleton();
|
|
MemoryManager::showResults();
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
terminal->getTerminal()->setAllowMemoryTrimnming( true );
|
|
terminal->pushEventCallback( [&closeOnExit]( const TerminalDisplay::Event& event ) {
|
|
if ( event.type == TerminalDisplay::EventType::TITLE ) {
|
|
windowStringData = event.eventData;
|
|
win->setTitle( "eterm - " + windowStringData );
|
|
} else if ( event.type == TerminalDisplay::EventType::PROCESS_EXIT &&
|
|
closeOnExit.Get() ) {
|
|
win->close();
|
|
}
|
|
} );
|
|
if ( shell )
|
|
terminal->setKeepAlive( false );
|
|
|
|
if ( colorScheme ) {
|
|
auto selColorScheme = terminalColorSchemes.find( colorScheme.Get() );
|
|
if ( selColorScheme != terminalColorSchemes.end() )
|
|
terminal->setColorScheme( selColorScheme->second );
|
|
}
|
|
|
|
if ( !executeInShell.Get().empty() )
|
|
terminal->executeFile( executeInShell.Get() );
|
|
|
|
win->startTextInput();
|
|
|
|
win->getInput()->pushCallback( &inputCallback );
|
|
|
|
win->runMainLoop( [] {
|
|
bool termNeedsUpdate = false;
|
|
win->getInput()->update();
|
|
|
|
if ( terminal )
|
|
termNeedsUpdate = !terminal->update();
|
|
|
|
if ( terminal && ( benchmarkMode || terminal->isDirty() ) &&
|
|
( !termNeedsUpdate || lastRender.getElapsedTime() >= frameTime ) ) {
|
|
lastRender.restart();
|
|
win->clear();
|
|
terminal->draw();
|
|
win->display();
|
|
} else if ( !benchmarkMode && !termNeedsUpdate ) {
|
|
win->getInput()->waitEvent( Milliseconds( win->hasFocus() ? 16 : 100 ) );
|
|
}
|
|
|
|
if ( benchmarkMode && secondsCounter.getElapsedTime() >= Seconds( 1 ) ) {
|
|
win->setTitle( "eterm - " + windowStringData + " - " +
|
|
String::toString( win->getFPS() ) + " FPS" );
|
|
secondsCounter.restart();
|
|
}
|
|
} );
|
|
}
|
|
|
|
terminal.reset();
|
|
|
|
Engine::destroySingleton();
|
|
|
|
MemoryManager::showResults();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|