Skip to content

Commit 0ed8567

Browse files
committed
The event queue now handles terminal resizing by calling the FApplication::onResize() method
1 parent 5d80f83 commit 0ed8567

11 files changed

Lines changed: 295 additions & 228 deletions

File tree

‎ChangeLog‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2026-10-14 Markus Gans <guru.mail@muenster.de>
2+
* The event queue now handles terminal resizing by calling
3+
the FApplication::onResize() method
4+
15
2026-10-11 Markus Gans <guru.mail@muenster.de>
26
* Optimize the FTermcap::hasDelay method
37

‎doc/event-processing.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ enum class Event : uInt8
8686
Show, // Widget is shown
8787
Hide, // Widget is hidden
8888
Close, // Widget close
89+
Log, // Writes log changes
8990
Timer, // Timer event occurred
9091
User // User defined event
9192
};

‎final/fapplication.cpp‎

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ FApplication::~FApplication() // destructor
125125
if ( eventInQueue() )
126126
event_queue.clear();
127127

128+
// Unset the resize handler
129+
FTermData::getInstance().setResizeHandler(nullptr);
130+
128131
resetLog();
129132
}
130133

@@ -487,6 +490,39 @@ void FApplication::processExternalUserEvent()
487490
// This method can be overloaded and replaced by own code
488491
}
489492

493+
//----------------------------------------------------------------------
494+
void FApplication::resize()
495+
{
496+
auto foutput_ptr = FVTerm::getFOutput();
497+
static auto& mouse = FMouseControl::getInstance();
498+
499+
// Detect and save the current terminal size
500+
foutput_ptr->detectTerminalSize();
501+
auto width = getDesktopWidth();
502+
auto height = getDesktopHeight();
503+
mouse.setMaxWidth (uInt16(width));
504+
mouse.setMaxHeight (uInt16(height));
505+
506+
// The screen content is now unknown
507+
foutput_ptr->clearTerminalState();
508+
foutput_ptr->clearTerminalAttributes();
509+
510+
// Determine the new terminal size
511+
const FRect old_term_geometry {getTermGeometry()};
512+
setDesktopWidgetSize (width, height);
513+
FRect term_geometry {getTermGeometry()};
514+
term_geometry.move (-1, -1);
515+
516+
if ( old_term_geometry.getSize() == term_geometry.getSize() )
517+
return;
518+
519+
resizeVTerm (term_geometry.getSize());
520+
resizeRegion ({term_geometry, getShadow()}, getVirtualDesktop());
521+
FVTerm::startDrawing(); // Avoid flickering - no update during adjustment
522+
adjustSizeGlobal();
523+
FVTerm::finishDrawing();
524+
}
525+
490526
//----------------------------------------------------------------------
491527
auto FApplication::event (FEvent* ev) -> bool
492528
{
@@ -533,6 +569,16 @@ void FApplication::onLog (FEvent*)
533569
has_log_data = false;
534570
}
535571

572+
//----------------------------------------------------------------------
573+
void FApplication::onResize (FResizeEvent* ev)
574+
{
575+
// This event handler can be reimplemented in a subclass
576+
// to receive resize events
577+
578+
processResizeEvent();
579+
ev->accept();
580+
}
581+
536582
//----------------------------------------------------------------------
537583
void FApplication::onClose (FCloseEvent*)
538584
{
@@ -596,6 +642,9 @@ void FApplication::init()
596642
// Initialize logging
597643
if ( ! getStartOptions().logfile_stream.is_open() )
598644
getLog()->setLineEnding(FLog::LineEnding::CRLF);
645+
646+
// Set the resize handler
647+
FTermData::getInstance().setResizeHandler( [this] () { queueResize(); } );
599648
}
600649

601650
//----------------------------------------------------------------------
@@ -1459,20 +1508,13 @@ auto FApplication::processParameters (const Args& args) -> FWidget*
14591508
//----------------------------------------------------------------------
14601509
void FApplication::processResizeEvent()
14611510
{
1462-
if ( ! has_terminal_resized ) // A SIGWINCH signal was received
1463-
return;
1511+
// This method will be called when the terminal size changes
14641512

1465-
auto foutput_ptr = FVTerm::getFOutput();
1466-
foutput_ptr->detectTerminalSize(); // Detect and save the current terminal size
1467-
static auto& mouse = FMouseControl::getInstance();
1468-
mouse.setMaxWidth (uInt16(getDesktopWidth()));
1469-
mouse.setMaxHeight (uInt16(getDesktopHeight()));
1470-
FResizeEvent r_ev(Event::Resize);
1471-
sendEvent(internal::var::app_object, &r_ev);
1472-
has_terminal_resized = false;
1513+
resize();
1514+
redraw();
14731515

1474-
if ( r_ev.isAccepted() )
1475-
foutput_ptr->commitTerminalResize();
1516+
has_terminal_resized = false;
1517+
FVTerm::getFOutput()->commitTerminalResize();
14761518
}
14771519

14781520
//----------------------------------------------------------------------
@@ -1562,6 +1604,18 @@ void FApplication::queueLog()
15621604
FApplication::queueEvent(this, std::move(ev));
15631605
}
15641606

1607+
//----------------------------------------------------------------------
1608+
void FApplication::queueResize()
1609+
{
1610+
if ( has_terminal_resized ) // A SIGWINCH signal was received
1611+
return;
1612+
1613+
has_terminal_resized = true;
1614+
1615+
auto ev = std::make_unique<FEvent>(Event::Resize);
1616+
FApplication::queueEvent(this, std::move(ev));
1617+
}
1618+
15651619
//----------------------------------------------------------------------
15661620
void FApplication::processLogger() const
15671621
{
@@ -1583,12 +1637,11 @@ auto FApplication::processNextEvent() -> bool
15831637
{
15841638
uInt num_events{0};
15851639

1586-
if ( hasDataInQueue() || hasTerminalResized() || isNextEventTimeout() )
1640+
if ( hasDataInQueue() || isNextEventTimeout() )
15871641
{
15881642
time_last_event = FObjectTimer::getCurrentTime();
15891643
num_events += processTimerEvent();
15901644
processInput();
1591-
processResizeEvent(); // when the terminal size has changed
15921645
sendQueuedEvents();
15931646
processTerminalScreenUpdate();
15941647
}
@@ -1607,14 +1660,6 @@ void FApplication::performTimerAction (FObject* receiver, FEvent* event)
16071660
sendEvent (receiver, event);
16081661
}
16091662

1610-
//----------------------------------------------------------------------
1611-
inline auto FApplication::hasTerminalResized() -> bool
1612-
{
1613-
auto foutput_ptr = FVTerm::getFOutput();
1614-
has_terminal_resized = foutput_ptr->hasTerminalResized();
1615-
return has_terminal_resized;
1616-
}
1617-
16181663
//----------------------------------------------------------------------
16191664
auto FApplication::isEventProcessable ( FObject* receiver
16201665
, const FEvent* event ) -> bool

‎final/fapplication.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,15 @@ class FApplication : public FWidget
162162
void cb_exitApp (FWidget*) const;
163163

164164
protected:
165+
// Methods
165166
virtual void processExternalUserEvent();
167+
void resize() override;
166168

167169
// Event handlers
168170
auto event (FEvent*) -> bool override;
169171
virtual void onDraw (FEvent*);
170172
virtual void onLog (FEvent*);
173+
void onResize (FResizeEvent*) override;
171174
void onClose (FCloseEvent*) override;
172175

173176
private:
@@ -244,10 +247,10 @@ class FApplication : public FWidget
244247
void processTerminalScreenUpdate() const;
245248
void processRedraw();
246249
void queueLog();
250+
void queueResize();
247251
void processLogger() const;
248252
auto processNextEvent() -> bool;
249253
void performTimerAction (FObject*, FEvent*) override;
250-
auto hasTerminalResized() -> bool;
251254
static auto isEventProcessable (FObject*, const FEvent*) -> bool;
252255
static auto isNextEventTimeout() -> bool;
253256

‎final/fwidget.cpp‎

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ auto FWidget::getColorTheme() -> std::shared_ptr<FWidgetColors>&
184184
}
185185

186186
//----------------------------------------------------------------------
187-
auto FWidget::doubleFlatLine_ref (Side side) -> std::vector<bool>&
187+
auto FWidget::mergingBorder_ref (Side side) -> std::vector<bool>&
188188
{
189189
auto& mask = merging_border_mask;
190190

@@ -838,31 +838,9 @@ void FWidget::redraw (RedrawMode redraw_mode)
838838
//----------------------------------------------------------------------
839839
void FWidget::resize()
840840
{
841-
if ( isRootWidget() )
842-
{
843-
// The screen content is now unknown
844-
auto foutput_ptr = FVTerm::getFOutput();
845-
foutput_ptr->clearTerminalState();
846-
foutput_ptr->clearTerminalAttributes();
847-
// Determine the new terminal size
848-
const FRect old_term_geometry {getTermGeometry()};
849-
determineDesktopSize();
850-
FRect term_geometry {getTermGeometry()};
851-
term_geometry.move (-1, -1);
852-
853-
if ( old_term_geometry.getSize() == term_geometry.getSize() )
854-
return;
855-
856-
resizeVTerm (term_geometry.getSize());
857-
resizeRegion ({term_geometry, getShadow()}, getVirtualDesktop());
858-
FVTerm::startDrawing(); // Avoid flickering - no update during adjustment
859-
adjustSizeGlobal();
860-
FVTerm::finishDrawing();
861-
}
862-
else
863-
adjustSize();
841+
adjustSize();
864842

865-
// resize the four double-flatline-masks
843+
// Resize the four merging border masks
866844
merging_border_mask.setSize (getWidth(), getHeight());
867845
}
868846

@@ -1189,6 +1167,16 @@ void FWidget::setTermOffsetWithPadding()
11891167
);
11901168
}
11911169

1170+
//----------------------------------------------------------------------
1171+
void FWidget::setDesktopWidgetSize (std::size_t width, std::size_t height)
1172+
{
1173+
wsize.setRect(1, 1, width, height);
1174+
adjust_wsize = wsize;
1175+
woffset.setRect(0, 0, width, height);
1176+
auto r = internal::var::root_widget;
1177+
wclient_offset.setRect(r->padding.left, r->padding.top, width, height);
1178+
}
1179+
11921180
//----------------------------------------------------------------------
11931181
void FWidget::initTerminal()
11941182
{
@@ -1442,12 +1430,10 @@ void FWidget::onAccel (FAccelEvent*)
14421430
}
14431431

14441432
//----------------------------------------------------------------------
1445-
void FWidget::onResize (FResizeEvent* ev)
1433+
void FWidget::onResize (FResizeEvent*)
14461434
{
1447-
// The terminal was resized
1448-
internal::var::root_widget->resize();
1449-
internal::var::root_widget->redraw();
1450-
ev->accept();
1435+
// This event handler can be reimplemented in a subclass
1436+
// to receive a resized event
14511437
}
14521438

14531439
//----------------------------------------------------------------------
@@ -1482,11 +1468,7 @@ void FWidget::determineDesktopSize()
14821468
detectTerminalSize();
14831469
auto width = getDesktopWidth();
14841470
auto height = getDesktopHeight();
1485-
wsize.setRect(1, 1, width, height);
1486-
adjust_wsize = wsize;
1487-
woffset.setRect(0, 0, width, height);
1488-
auto r = internal::var::root_widget;
1489-
wclient_offset.setRect(r->padding.left, r->padding.top, width, height);
1471+
setDesktopWidgetSize(width, height);
14901472
}
14911473

14921474
//----------------------------------------------------------------------

‎final/fwidget.h‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class FWidget : public FVTerm
172172
auto getStatusBarMessage() const -> FString;
173173
auto getForegroundColor() const noexcept -> FColor; // get the primary
174174
auto getBackgroundColor() const noexcept -> FColor; // widget colors
175-
auto doubleFlatLine_ref (Side) -> std::vector<bool>&;
175+
auto mergingBorder_ref (Side) -> std::vector<bool>&;
176176
// Positioning and sizes accessors...
177177
auto getX() const -> int;
178178
auto getY() const -> int;
@@ -328,6 +328,7 @@ class FWidget : public FVTerm
328328
void setParentOffset();
329329
void setTermOffset();
330330
void setTermOffsetWithPadding();
331+
void setDesktopWidgetSize (std::size_t, std::size_t);
331332

332333
// Methods
333334
void initTerminal() override;
@@ -470,9 +471,7 @@ class FWidget : public FVTerm
470471
auto sendFocusInEvent (FWidget*, FocusTypes) const -> bool;
471472
void processDestroy() const;
472473
virtual void draw();
473-
public:
474474
void recursiveDraw();
475-
private:
476475
void drawChildren();
477476
void adjustWidget();
478477
void adjustSizeWithinRegion (FRect&) const;
@@ -530,6 +529,9 @@ class FWidget : public FVTerm
530529
static bool init_terminal;
531530
static bool init_desktop;
532531

532+
// Friend class
533+
friend class FApplication;
534+
533535
// Friend functions
534536
friend struct GenericBoxData;
535537
friend struct GenericBlockShadowData;

‎final/output/tty/ftermdata.h‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ class FTermData final
149149
// Using-declaration
150150
using EncodingMap = std::unordered_map<std::string, Encoding>;
151151

152+
// After switching to the new event loop implementation,
153+
// this handler will no longer be necessary.
154+
using ResizeHandler = std::function<void()>;
155+
152156
// Constructors
153157
FTermData () = default;
154158

@@ -208,6 +212,7 @@ class FTermData final
208212
void setVGAFont (bool = true) noexcept;
209213
void setMonochron (bool = true) noexcept;
210214
void setTermResized (bool = true);
215+
void setResizeHandler (ResizeHandler&&);
211216
void setTermType (const std::string&);
212217
void setTermType (FTermType);
213218
void unsetTermType (FTermType);
@@ -221,6 +226,9 @@ class FTermData final
221226
#endif
222227

223228
private:
229+
// Method
230+
void callResizeHandler();
231+
224232
// Encoding-related fields
225233
struct EncodingInfo
226234
{
@@ -254,6 +262,10 @@ class FTermData final
254262
uInt baudrate{0};
255263
std::string termtype{};
256264
std::string term_file_name{};
265+
266+
// After switching to the new event loop implementation,
267+
// this handler will no longer be necessary.
268+
ResizeHandler resize_handler;
257269
};
258270

259271
// Synchronization and state
@@ -495,11 +507,22 @@ inline void FTermData::setTermResized (bool resize)
495507
std::lock_guard<std::mutex> resize_lock_guard(synchronization_state.resize_mutex);
496508

497509
if ( resize )
510+
{
498511
++synchronization_state.resize_count;
512+
callResizeHandler();
513+
}
499514
else if ( synchronization_state.resize_count.load() > 0 )
500515
--synchronization_state.resize_count;
501516
}
502517

518+
//----------------------------------------------------------------------
519+
inline void FTermData::setResizeHandler (ResizeHandler&& handler)
520+
{
521+
// After switching to the new event loop implementation,
522+
// this method will no longer be necessary.
523+
terminal_settings.resize_handler = std::move(handler);
524+
}
525+
503526
//----------------------------------------------------------------------
504527
inline void FTermData::setTermType (const std::string& name)
505528
{
@@ -547,6 +570,15 @@ inline void FTermData::setFramebufferBpp (int bpp) noexcept
547570
{ terminal_settings.framebuffer_bpp = bpp; }
548571
#endif
549572

573+
//----------------------------------------------------------------------
574+
inline void FTermData::callResizeHandler()
575+
{
576+
// After switching to the new event loop implementation,
577+
// this method will no longer be necessary.
578+
if ( terminal_settings.resize_handler )
579+
terminal_settings.resize_handler();
580+
}
581+
550582
} // namespace finalcut
551583

552584
#endif // FTERMDATA_H

0 commit comments

Comments
 (0)