Terminal: Add auto-scroll when selecting and mouse cursor moves out of vertical view range.

Fix tab owned widget focus.
Fix overlapping shortcuts and terminal shortcuts in terminal.
This commit is contained in:
Martín Lucas Golini
2025-12-19 14:20:17 -03:00
parent abda8775ac
commit e5a67727c4
7 changed files with 82 additions and 16 deletions

View File

@@ -173,7 +173,7 @@ class TerminalDisplay : public ITerminalDisplay {
virtual void drawCursor( int cx, int cy, TerminalGlyph g, int ox, int oy, TerminalGlyph og );
virtual void drawEnd();
virtual bool update();
virtual bool update( bool isMouseOverMe = true );
void executeFile( const std::string& cmd );
@@ -200,6 +200,8 @@ class TerminalDisplay : public ITerminalDisplay {
virtual void onKeyDown( const Keycode& keyCode, const Uint32& chr, const Uint32& mod,
const Scancode& scancode );
bool isRegisteredShortcut( const Keycode& keyCode, const Uint32& mod ) const;
Font* getFont() const;
void setFont( Font* font );
@@ -319,6 +321,7 @@ class TerminalDisplay : public ITerminalDisplay {
Uint32 mQuadVertex{ 6 };
Primitives mPrimitives;
Vector2u mCurGridPos;
Clock mLastAutoScroll;
std::string mProgram;
std::vector<std::string> mArgs;

View File

@@ -628,7 +628,7 @@ void TerminalDisplay::setKeepAlive( bool keepAlive ) {
mKeepAlive = keepAlive;
}
bool TerminalDisplay::update() {
bool TerminalDisplay::update( bool isMouseOverMe ) {
bool ret = true;
if ( mFocus && isBlinkingCursor() && mClock.getElapsedTime().asSeconds() > 0.7 ) {
mMode ^= MODE_BLINK;
@@ -641,6 +641,14 @@ bool TerminalDisplay::update() {
if ( histi != mTerminal->getHistorySize() )
sendEvent( { EventType::HISTORY_LENGTH_CHANGE } );
}
if ( mAlreadyClickedLButton ) {
if ( !( mWindow->getInput()->getPressTrigger() & EE_BUTTON_LMASK ) ) {
mWindow->getInput()->captureMouse( false );
} else if ( !isMouseOverMe ) {
onMouseMove( mWindow->getInput()->getMousePos(),
mWindow->getInput()->getPressTrigger() );
}
}
return ret;
}
@@ -826,6 +834,22 @@ void TerminalDisplay::onMouseMove( const Vector2i& pos, const Uint32& flags ) {
bool shiftPressed = ( mWindow->getInput()->getModState() & KEYMOD_SHIFT ) != 0;
bool isCapturingMouse = isAppCapturingMouse() && !shiftPressed;
if ( !isAltScr() && !isCapturingMouse && ( flags & EE_BUTTON_LMASK ) &&
mAlreadyClickedLButton ) {
Vector2f relPos = { pos.x - mPosition.x - mPadding.Left,
pos.y - mPosition.y - mPadding.Top };
if ( mLastAutoScroll.getElapsedTime() >= Milliseconds( 16 ) ) {
if ( relPos.y < 0 ) {
action( TerminalShortcutAction::SCROLLUP_ROW );
mLastAutoScroll.restart();
} else if ( relPos.y > mSize.getHeight() ) {
action( TerminalShortcutAction::SCROLLDOWN_ROW );
mLastAutoScroll.restart();
}
}
}
if ( !isCapturingMouse && ( flags & EE_BUTTON_LMASK ) &&
( mTerminal->getSelectionMode() == TerminalSelectionMode::SEL_EMPTY ||
mTerminal->getSelectionMode() == TerminalSelectionMode::SEL_READY ) ) {
@@ -856,6 +880,7 @@ void TerminalDisplay::onMouseDown( const Vector2i& pos, const Uint32& flags ) {
mTerminal->selstart( gridPos.x, gridPos.y, 0 );
mDraggingSel = true;
invalidateLines();
mWindow->getInput()->captureMouse( true );
}
} else if ( flags & EE_BUTTON_MMASK ) {
if ( !mAlreadyClickedMButton ) {
@@ -891,8 +916,10 @@ void TerminalDisplay::onMouseUp( const Vector2i& pos, const Uint32& flags ) {
Uint32 smod = sanitizeMod( mWindow->getInput()->getModState() );
if ( flags & EE_BUTTON_LMASK )
if ( flags & EE_BUTTON_LMASK ) {
mAlreadyClickedLButton = false;
mWindow->getInput()->captureMouse( false );
}
if ( flags & EE_BUTTON_MMASK )
mAlreadyClickedMButton = false;
@@ -1586,6 +1613,30 @@ void TerminalDisplay::onTextEditing( const String&, const Int32&, const Int32& )
updateIMELocation();
}
bool TerminalDisplay::isRegisteredShortcut( const Keycode& keyCode, const Uint32& mod ) const {
Uint32 smod = sanitizeMod( mod );
auto scIt = terminalKeyMap.Shortcuts().find( keyCode );
if ( scIt != terminalKeyMap.Shortcuts().end() ) {
for ( auto& k : scIt->second ) {
if ( k.mask == KEYMOD_CTRL_SHIFT_ALT_META || k.mask == smod ) {
if ( IS_SET( MODE_APPKEYPAD ) ? k.appkey < 0 : k.appkey > 0 )
continue;
if ( IS_SET( MODE_NUMLOCK ) && k.appkey == 2 )
continue;
if ( IS_SET( MODE_APPCURSOR ) ? k.appcursor < 0 : k.appcursor > 0 )
continue;
if ( !k.altscrn || ( k.altscrn == ( mEmulator->tisaltscr() ? 1 : -1 ) ) ) {
return true;
}
}
}
}
return false;
}
void TerminalDisplay::onKeyDown( const Keycode& keyCode, const Uint32& /*chr*/, const Uint32& mod,
const Scancode& scancode ) {
if ( mWindow->getIME().isEditing() )
@@ -1614,7 +1665,7 @@ void TerminalDisplay::onKeyDown( const Keycode& keyCode, const Uint32& /*chr*/,
}
if ( mod & KEYMOD_CTRL ) {
// I really dont like this, as it depends on the undelying backend implementation (SDL in
// I really dont like this, as it depends on the underlying backend implementation (SDL in
// this case)
if ( ( scancode >= SCANCODE_A && scancode <= SCANCODE_0 ) ||
SCANCODE_LEFTBRACKET == scancode || SCANCODE_RIGHTBRACKET == scancode ) {
@@ -1748,6 +1799,12 @@ void TerminalDisplay::setFocus( bool focus ) {
if ( focus == mFocus )
return;
// focus loss
if ( mFocus && !focus && mAlreadyClickedMButton ) {
mWindow->getInput()->captureMouse( false );
}
mFocus = focus;
bool modeFocus = mMode & MODE_FOCUSED;
if ( mFocus != modeFocus ) {

View File

@@ -1638,9 +1638,9 @@ void TerminalEmulator::csihandle( void ) {
switch ( mCsiescseq.mode[1] ) {
case '4': /* Extended underline styles ESC[>4;Nm */
// Extended underline styles - fallback to standard underline
DEFAULT( mCsiescseq.arg[0], 1 );
/* DEFAULT( mCsiescseq.arg[0], 1 );
switch ( mCsiescseq.arg[0] ) {
/* case 0: // No underline - fallback to ESC[24m
case 0: // No underline - fallback to ESC[24m
{
int fallback_args[] = { 24 }; // Reset underline
tsetattr( fallback_args, 1 );
@@ -1653,10 +1653,10 @@ void TerminalEmulator::csihandle( void ) {
{
int fallback_args[] = { 4 }; // Standard underline
tsetattr( fallback_args, 1 );
} break; */
} break;
default:
goto unknown;
}
} */
break;
default:
goto unknown;

View File

@@ -315,7 +315,7 @@ const std::shared_ptr<TerminalDisplay>& UITerminal::getTerm() const {
void UITerminal::scheduledUpdate( const Time& ) {
if ( !mTerm )
return;
mTerm->update();
mTerm->update( isMouseOverMeOrChildren() );
if ( mTerm->isDirty() && isVisible() )
invalidateDraw();
@@ -451,11 +451,14 @@ Uint32 UITerminal::onKeyDown( const KeyEvent& event ) {
if ( mUISceneNode->getUIEventDispatcher()->justGainedFocus() )
return 0;
std::string cmd = mKeyBindings.getCommandFromKeyBind( { event.getKeyCode(), event.getMod() } );
if ( !cmd.empty() ) {
if ( !mExclusiveMode || cmd == getExclusiveModeToggleCommandName() )
execute( cmd );
return 1;
if ( !mTerm->isRegisteredShortcut( event.getKeyCode(), event.getMod() ) ) {
std::string cmd =
mKeyBindings.getCommandFromKeyBind( { event.getKeyCode(), event.getMod() } );
if ( !cmd.empty() ) {
if ( !mExclusiveMode || cmd == getExclusiveModeToggleCommandName() )
execute( cmd );
return 1;
}
}
mTerm->onKeyDown( event.getKeyCode(), event.getChar(), event.getMod(), event.getScancode() );