Skip to content

Commit

Permalink
Merge branch 'elfmz:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
deep-soft authored Nov 11, 2024
2 parents 8d69f43 + d1fed9a commit f0fa790
Show file tree
Hide file tree
Showing 21 changed files with 1,057 additions and 730 deletions.
5 changes: 4 additions & 1 deletion WinPort/WinPort.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ extern "C" {
#ifndef FAR_PYTHON_GEN
int WinPortMain(const char *full_exe_path, int argc, char **argv, int (*AppMain)(int argc, char **argv));
void WinPortHelp();
const wchar_t *WinPortBackend();

// entity = -1 - current backend flavor
// entity = [0 .. until NULL result) - version information of different components
const char *WinPortBackendInfo(int entity);

// true means far2l runs under smoke testing and code must
// not skip events from input queue that sometimes used to make UX smoother
Expand Down
81 changes: 71 additions & 10 deletions WinPort/src/APIConsole.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <mutex>
#include <map>
#include <vector>
#include <atomic>
#include <stdexcept>
#include <debug.h>
#include <unistd.h>

#include "WinPort.h"
#include "Backend.h"
Expand All @@ -16,15 +18,41 @@ struct ForkedConsole
IConsoleOutput *con_out{nullptr};
};

static IConsoleOutput *ChooseConOut(HANDLE hConsole)
static std::atomic<IConsoleOutput *> s_shadow_out{nullptr};
static std::atomic<int> s_shadow_usecnt{0};

class ChooseConOut
{
if (!hConsole) {
return g_winport_con_out;
IConsoleOutput *_chosen{};
bool _using_shadow{false};

public:
ChooseConOut(HANDLE hConsole)
{
if (hConsole) {
ForkedConsole *fc = (ForkedConsole *)hConsole;
ASSERT(fc->magic == FORKED_CONSOLE_MAGIC);
_chosen = fc->con_out;
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 {
_using_shadow = true;
}
}
ForkedConsole *fc = (ForkedConsole *)hConsole;
ASSERT(fc->magic == FORKED_CONSOLE_MAGIC);
return fc->con_out;
}
~ChooseConOut()
{
if (_using_shadow) {
--s_shadow_usecnt;
}
}
inline operator IConsoleOutput *() { return _chosen; }
inline IConsoleOutput *operator->() { return _chosen; }
};

static IConsoleInput *ChooseConIn(HANDLE hConsole)
{
Expand All @@ -38,6 +66,38 @@ static IConsoleInput *ChooseConIn(HANDLE hConsole)

extern "C" {

WINPORT_DECL(FreezeConsoleOutput,VOID,())
{
if (s_shadow_out == nullptr) {
try {
// use NULL handle to make app treat its scroll callbacks as from main output
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 (...) {
fprintf(stderr, "%s: exception\n", __FUNCTION__);
}
} else {
fprintf(stderr, "%s: called while already frozen\n", __FUNCTION__);
}
}

WINPORT_DECL(UnfreezeConsoleOutput,VOID,())
{
IConsoleOutput *shadow_out = s_shadow_out.exchange(nullptr);
if (shadow_out) {
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__);
}
}

WINPORT_DECL(ForkConsole,HANDLE,())
{
ForkedConsole *fc = NULL;
Expand Down Expand Up @@ -123,7 +183,7 @@ extern "C" {
WINPORT_DECL(GetConsoleScreenBufferInfo,BOOL,(HANDLE hConsoleOutput,CONSOLE_SCREEN_BUFFER_INFO *lpConsoleScreenBufferInfo))
{
unsigned int width = 0, height = 0;
auto *con_out = ChooseConOut(hConsoleOutput);
ChooseConOut con_out(hConsoleOutput);
con_out->GetSize(width, height);
lpConsoleScreenBufferInfo->dwCursorPosition = con_out->GetCursor();
lpConsoleScreenBufferInfo->wAttributes = con_out->GetAttributes();
Expand Down Expand Up @@ -429,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
5 changes: 5 additions & 0 deletions WinPort/src/APIOther.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "WinPort.h"
#include "WinPortHandle.h"
#include "PathHelpers.h"
#include "Backend.h"
#include <utils.h>
#include <errno.h>

Expand Down Expand Up @@ -49,4 +50,8 @@ extern "C" {
return TRUE;
}

const char *WinPortBackendInfo(int entity)
{
return g_winport_con_out->BackendInfo(entity);
}
}
8 changes: 5 additions & 3 deletions WinPort/src/Backend/Backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/// Something changed in code below.
/// "WinCompat.h" changed in a way affecting code below.
/// Behavior of backend's code changed in incompatible way.
#define FAR2L_BACKEND_ABI_VERSION 0x0B
#define FAR2L_BACKEND_ABI_VERSION 0x0C

#define NODETECT_NONE 0x0000
#define NODETECT_XI 0x0001
Expand Down Expand Up @@ -44,6 +44,7 @@ class IConsoleOutputBackend
virtual bool OnConsoleSetBasePalette(void *pbuff) = 0;
virtual void OnConsoleOverrideColor(DWORD Index, DWORD *ColorFG, DWORD *ColorBK) = 0;
virtual void OnConsoleSetCursorBlinkTime(DWORD interval) = 0;
virtual const char *OnConsoleBackendInfo(int entity) = 0;
};

class IClipboardBackend
Expand Down Expand Up @@ -213,7 +214,9 @@ 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;

inline std::wstring GetTitle()
{
Expand Down Expand Up @@ -249,7 +252,6 @@ class IConsoleOutput

extern IConsoleOutput *g_winport_con_out;
extern IConsoleInput *g_winport_con_in;
extern const wchar_t *g_winport_backend;

//////////////////////////////////////////////////////////////////////////////////

Expand Down
72 changes: 36 additions & 36 deletions WinPort/src/Backend/TTY/TTYBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,41 +170,10 @@ bool TTYBackend::Startup()
return true;
}

static wchar_t s_backend_identification[8] = L"TTY";

static void AppendBackendIdentificationChar(char ch)
void TTYBackend::BackendInfoChanged()
{
const size_t l = wcslen(s_backend_identification);
if (l + 1 >= ARRAYSIZE(s_backend_identification)) {
abort();
}
s_backend_identification[l + 1] = 0;
s_backend_identification[l] = (unsigned char)ch;
}

void TTYBackend::UpdateBackendIdentification()
{
s_backend_identification[3] = 0;

if (_far2l_tty || _ttyx || _using_extension) {
AppendBackendIdentificationChar('|');
}

if (_far2l_tty) {
AppendBackendIdentificationChar('F');

} else if (_ttyx || _using_extension) {
if (_ttyx) {
AppendBackendIdentificationChar('X');
}
if (_using_extension) {
AppendBackendIdentificationChar(_using_extension);
} else if (_ttyx && _ttyx->HasXi()) {
AppendBackendIdentificationChar('i');
}
}

g_winport_backend = s_backend_identification;
std::lock_guard<std::mutex> lock(_backend_info);
_backend_info.flavor.clear();
}

static bool UnderWayland()
Expand Down Expand Up @@ -245,7 +214,7 @@ void TTYBackend::ReaderThread()
ChooseSimpleClipboardBackend();
}
}
UpdateBackendIdentification();
BackendInfoChanged();
prev_far2l_tty = _far2l_tty;

{
Expand Down Expand Up @@ -1057,7 +1026,7 @@ void TTYBackend::OnUsingExtension(char extension)
{
if (_using_extension != extension) {
_using_extension = extension;
UpdateBackendIdentification();
BackendInfoChanged();
}
}

Expand Down Expand Up @@ -1239,6 +1208,37 @@ bool TTYBackend::OnConsoleBackgroundMode(bool TryEnterBackgroundMode)
return true;
}

const char *TTYBackend::OnConsoleBackendInfo(int entity)
{
if (entity != -1)
return nullptr;

std::lock_guard<std::mutex> lock(_backend_info);
if (_backend_info.flavor.empty()) {
_backend_info.flavor.reserve(16); // avoid reallocation ever then
_backend_info.flavor = "TTY";

if (_far2l_tty || _ttyx || _using_extension) {
_backend_info.flavor+= '|';
}

if (_far2l_tty) {
_backend_info.flavor+= 'F';
} else if (_ttyx || _using_extension) {
if (_ttyx) {
_backend_info.flavor+= 'X';
}
if (_using_extension) {
_backend_info.flavor+= _using_extension;
} else if (_ttyx && _ttyx->HasXi()) {
_backend_info.flavor+= 'i';
}
}
}

return _backend_info.flavor.c_str();
}


static void OnSigWinch(int)
{
Expand Down
4 changes: 3 additions & 1 deletion WinPort/src/Backend/TTY/TTYBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
void ReaderThread();
void ReaderLoop();
void WriterThread();
void UpdateBackendIdentification();
void BackendInfoChanged();

std::condition_variable _async_cond;
std::mutex _async_mutex;
Expand All @@ -67,6 +67,7 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
std::atomic<bool> _largest_window_size_ready{false};
std::atomic<bool> _flush_input_queue{false};

struct BI : std::mutex { std::string flavor; } _backend_info;

struct Far2lInteractData
{
Expand Down Expand Up @@ -139,6 +140,7 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
virtual bool OnConsoleSetBasePalette(void *pbuff);
virtual void OnConsoleOverrideColor(DWORD Index, DWORD *ColorFG, DWORD *ColorBK);
virtual void OnConsoleSetCursorBlinkTime(DWORD interval);
const char *OnConsoleBackendInfo(int entity);

// ITTYInputSpecialSequenceHandler
virtual void OnUsingExtension(char extension);
Expand Down
Loading

0 comments on commit f0fa790

Please sign in to comment.