Skip to content

Commit

Permalink
some fixes for recent change
Browse files Browse the repository at this point in the history
  • Loading branch information
elfmz committed Nov 10, 2024
1 parent 9242bed commit d1fed9a
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 21 deletions.
35 changes: 23 additions & 12 deletions WinPort/src/APIConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,36 @@ struct ForkedConsole
};

static std::atomic<IConsoleOutput *> s_shadow_out{nullptr};
static std::atomic<int> s_out_usecnt{0};
static std::atomic<int> s_shadow_usecnt{0};

class ChooseConOut
{
IConsoleOutput *_chosen{};
bool _using_shadow{false};

public:
ChooseConOut(HANDLE hConsole)
{
++s_out_usecnt;
if (hConsole) {
ForkedConsole *fc = (ForkedConsole *)hConsole;
ASSERT(fc->magic == FORKED_CONSOLE_MAGIC);
_chosen = fc->con_out;
} else if (LIKELY(s_shadow_out == nullptr)) {
return;
}
++s_shadow_usecnt;
_chosen = s_shadow_out;
if (LIKELY(_chosen == nullptr)) {
--s_shadow_usecnt; // not gonna use shadow
_chosen = g_winport_con_out;
} else {
_chosen = s_shadow_out;
_using_shadow = true;
}
}
~ChooseConOut()
{
--s_out_usecnt;
if (_using_shadow) {
--s_shadow_usecnt;
}
}
inline operator IConsoleOutput *() { return _chosen; }
inline IConsoleOutput *operator->() { return _chosen; }
Expand All @@ -64,9 +71,12 @@ extern "C" {
if (s_shadow_out == nullptr) {
try {
// use NULL handle to make app treat its scroll callbacks as from main output
s_shadow_out = g_winport_con_out->ForkConsoleOutput(NULL);
IConsoleOutput *shadow_out = g_winport_con_out->ForkConsoleOutput(NULL);
shadow_out = s_shadow_out.exchange(shadow_out);
if (shadow_out) {
g_winport_con_out->JoinConsoleOutput(shadow_out);
}
} catch (...) {
s_shadow_out = nullptr;
fprintf(stderr, "%s: exception\n", __FUNCTION__);
}
} else {
Expand All @@ -76,13 +86,13 @@ extern "C" {

WINPORT_DECL(UnfreezeConsoleOutput,VOID,())
{
static IConsoleOutput *shadow_out = s_shadow_out;
IConsoleOutput *shadow_out = s_shadow_out.exchange(nullptr);
if (shadow_out) {
s_shadow_out = nullptr;
while (s_out_usecnt != 0) {
while (s_shadow_usecnt != 0) {
usleep(1);
}
g_winport_con_out->JoinConsoleOutput(shadow_out);
g_winport_con_out->RepaintsDeferFinish(true);
} else {
fprintf(stderr, "%s: called while not frozen\n", __FUNCTION__);
}
Expand Down Expand Up @@ -479,10 +489,11 @@ extern "C" {

WINPORT_DECL(SetConsoleRepaintsDefer, VOID, (HANDLE hConsoleOutput, BOOL Deferring))
{
ChooseConOut con_out(hConsoleOutput);
if (Deferring) {
ChooseConOut(hConsoleOutput)->RepaintsDeferStart();
con_out->RepaintsDeferStart();
} else {
ChooseConOut(hConsoleOutput)->RepaintsDeferFinish();
con_out->RepaintsDeferFinish(false);
}
}

Expand Down
2 changes: 1 addition & 1 deletion WinPort/src/Backend/Backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class IConsoleOutput
virtual bool SetBasePalette(void *p) = 0;
virtual void OverrideColor(DWORD Index, DWORD *ColorFG, DWORD *ColorBK) = 0;
virtual void RepaintsDeferStart() = 0;
virtual void RepaintsDeferFinish() = 0;
virtual void RepaintsDeferFinish(bool force) = 0;

virtual const char *BackendInfo(int entity) = 0;

Expand Down
24 changes: 21 additions & 3 deletions WinPort/src/Backend/WX/wxMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
// If time between adhoc text copy and mouse button release less then this value then text will not be copied. Used to protect against unwanted copy-paste-s
#define QEDIT_COPY_MINIMAL_DELAY 150

// This defines muh much time UI remain frozen after user released qedit, that
// allows user to quickly select another location before all shadowed output changes applied
#define QEDIT_UNFREEZE_DELAY 1000

#if (wxCHECK_VERSION(3, 0, 5) || (wxCHECK_VERSION(3, 0, 4) && WX304PATCH)) && !(wxCHECK_VERSION(3, 1, 0) && !wxCHECK_VERSION(3, 1, 3))
// wx version is greater than 3.0.5 (3.0.4 on Ubuntu 20) and not in 3.1.0-3.1.2
#define WX_ALT_NONLATIN
Expand Down Expand Up @@ -791,6 +795,12 @@ void WinPortPanel::OnTimerPeriodic(wxTimerEvent& event)
return;
}

if (_qedit_unfreeze_start_ticks != 0
&& WINPORT(GetTickCount)() - _qedit_unfreeze_start_ticks >= QEDIT_UNFREEZE_DELAY) {
WINPORT(UnfreezeConsoleOutput)();
_qedit_unfreeze_start_ticks = 0;
}

CheckForResizePending();
CheckPutText2CLip();
if (_mouse_qedit_start_ticks != 0 && WINPORT(GetTickCount)() - _mouse_qedit_start_ticks > QEDIT_COPY_MINIMAL_DELAY) {
Expand All @@ -799,7 +809,10 @@ void WinPortPanel::OnTimerPeriodic(wxTimerEvent& event)
_paint_context.BlinkCursor();
++_timer_idling_counter;
// stop timer if counter reached limit and cursor is visible and no other timer-dependent things remained
if (_timer_idling_counter >= g_TIMER_IDLING_CYCLES && _paint_context.CursorBlinkState() && _text2clip.empty()) {
if (_timer_idling_counter >= g_TIMER_IDLING_CYCLES
&& _paint_context.CursorBlinkState()
&& _qedit_unfreeze_start_ticks == 0
&& _text2clip.empty()) {
_periodic_timer->Stop();
}
}
Expand Down Expand Up @@ -1794,7 +1807,12 @@ void WinPortPanel::OnMouseQEdit( wxMouseEvent &event, COORD pos_char )
_mouse_qedit_start_ticks = WINPORT(GetTickCount)();
if (!_mouse_qedit_start_ticks) _mouse_qedit_start_ticks = 1;
_mouse_qedit_moved = false;
WINPORT(FreezeConsoleOutput)();
if (_qedit_unfreeze_start_ticks == 0) {
WINPORT(FreezeConsoleOutput)();
} else {
_qedit_unfreeze_start_ticks = 0;
}
_qedit_out_state = QOS_FROZEN_BUSY;
DamageAreaBetween(_mouse_qedit_start, _mouse_qedit_last);

} else if (_mouse_qedit_start_ticks != 0) {
Expand Down Expand Up @@ -1840,7 +1858,7 @@ void WinPortPanel::OnMouseQEdit( wxMouseEvent &event, COORD pos_char )
_mouse_qedit_start_ticks = 0;
DamageAreaBetween(_mouse_qedit_start, _mouse_qedit_last);
DamageAreaBetween(_mouse_qedit_start, pos_char);
WINPORT(UnfreezeConsoleOutput)();
_qedit_unfreeze_start_ticks = WINPORT(GetTickCount)();
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions WinPort/src/Backend/WX/wxMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ class WinPortPanel: public wxPanel, protected IConsoleOutputBackend
RP_DEFER,
RP_INSTANT
} _resize_pending{RP_NONE};
enum
{
QOS_NOT_FROZEN,
QOS_FROZEN_BUSY,
QOS_UNFREEZE_PENDING,
QOS_UNFREEZE_PENDING2,
} _qedit_out_state{QOS_NOT_FROZEN};
DWORD _qedit_unfreeze_start_ticks{0};
DWORD _mouse_state{0}, _mouse_qedit_start_ticks{0}, _mouse_qedit_moved{0};
COORD _mouse_qedit_start{}, _mouse_qedit_last{};
wchar_t _stolen_key{0};
Expand Down
13 changes: 9 additions & 4 deletions WinPort/src/ConsoleOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,14 +800,19 @@ void ConsoleOutput::RepaintsDeferStart()
ASSERT(_repaint_defer > 0);
}

void ConsoleOutput::RepaintsDeferFinish()
void ConsoleOutput::RepaintsDeferFinish(bool force)
{
std::vector<SMALL_RECT> deferred_repaints;
{
std::lock_guard<std::mutex> lock(_mutex);
ASSERT(_repaint_defer > 0);
--_repaint_defer;
deferred_repaints.swap(_deferred_repaints);
if (force) {
_repaint_defer = 0;
} else if (_repaint_defer > 0) {
--_repaint_defer;
}
if (_repaint_defer == 0) {
deferred_repaints.swap(_deferred_repaints);
}
if (!deferred_repaints.empty()) {
LockedChangeIdUpdate();
}
Expand Down
2 changes: 1 addition & 1 deletion WinPort/src/ConsoleOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class ConsoleOutput : public IConsoleOutput
virtual bool SetBasePalette(void *p);
virtual void OverrideColor(DWORD Index, DWORD *ColorFG, DWORD *ColorBK);
virtual void RepaintsDeferStart();
virtual void RepaintsDeferFinish();
virtual void RepaintsDeferFinish(bool force);

virtual IConsoleOutput *ForkConsoleOutput(HANDLE con_handle);
virtual void JoinConsoleOutput(IConsoleOutput *con_out);
Expand Down

0 comments on commit d1fed9a

Please sign in to comment.