added simple vertical tiling window manager

This commit is contained in:
Christian Burger 2022-05-03 11:23:32 +02:00
parent f8db9dc660
commit 0462a68c54
9 changed files with 140 additions and 20 deletions

View file

@ -53,7 +53,8 @@
"iostream": "cpp",
"stdexcept": "cpp",
"typeinfo": "cpp",
"pointers": "cpp"
"pointers": "cpp",
"list": "cpp"
},
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"C_Cpp.default.includePath": [

16
App.cpp
View file

@ -4,6 +4,8 @@
#include "App.hpp"
#include "Debug.hpp"
#include <NCurses/VerticalTilingWindowManager.hpp>
#include <NCurses/Window.hpp>
#include <NCurses/PtyWindow.hpp>
#include <unistd.h>
@ -20,13 +22,15 @@ namespace krikkel::NCurses
int DemoApp::run()
{
std::mutex writeMutex;
std::mutex ncursesMutex;
VerticalTilingWindowManager windowManager(Root_Window, &ncursesMutex);
PtyWindow *ptyWindow = new PtyWindow(&writeMutex
, Root_Window->lines()
, Root_Window->cols()
, 0
, 0);
new Window(&windowManager);
PtyWindow *ptyWindow = new PtyWindow(&ncursesMutex, 0, 0, 0, 0);
windowManager.addWindow(ptyWindow);
new Window(&windowManager);
windowManager.updateLayout();
windowManager.refresh();
if(fork() == 0)
{

View file

@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 17)
include(CTest)
enable_testing()
add_library(NCurses Window.cpp PtyWindow.cpp SingleUserInput.cpp Debug.cpp)
add_library(NCurses Window.cpp PtyWindow.cpp SingleUserInput.cpp Debug.cpp VerticalTilingWindowManager.cpp)
### path to own system includes
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/include")
@ -44,7 +44,7 @@ target_link_libraries(NCursesDemoApp NCurses)
### installation and packaging
set(NCURSES_SYSTEM_INCLUDE "include/NCurses")
set_target_properties(NCurses PROPERTIES PUBLIC_HEADER "${NCURSES_SYSTEM_INCLUDE}/Window.hpp;${NCURSES_SYSTEM_INCLUDE}/SingleUserInput.hpp;${NCURSES_SYSTEM_INCLUDE}/PtyWindow.hpp"
set_target_properties(NCurses PROPERTIES PUBLIC_HEADER "${NCURSES_SYSTEM_INCLUDE}/Window.hpp;${NCURSES_SYSTEM_INCLUDE}/SingleUserInput.hpp;${NCURSES_SYSTEM_INCLUDE}/PtyWindow.hpp;${NCURSES_SYSTEM_INCLUDE}/VerticalTilingWindowManager.hpp;"
VERSION "${CMAKE_PROJECT_VERSION}")
include(GNUInstallDirs)
install(TARGETS NCurses ARCHIVE

View file

@ -18,8 +18,8 @@ namespace krikkel::NCurses
using gsl::narrow;
using std::lock_guard;
PtyWindow::PtyWindow(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x)
: writeToNCursesMutex(writeToNCursesMutex), Window(lines, columns, y, x)
PtyWindow::PtyWindow(std::mutex *ncursesMutex, int lines, int columns, int y, int x)
: ncursesMutex(ncursesMutex), Window(lines, columns, y, x)
{
// to get the original terminal we need to shutdown ncurses for a moment
/// @todo maybe try `reset_prog_mode()` and `reset_shell_mode()` instead
@ -239,7 +239,7 @@ namespace krikkel::NCurses
character = *vTermCell.chars;
{
lock_guard nCursesLock(*writeToNCursesMutex);
lock_guard nCursesLock(*ncursesMutex);
setcchar(&converted, &character, formatting, colorPair, NULL);
move(cellPosition.row, cellPosition.col);
chgat(1, formatting, colorPair, NULL);
@ -249,14 +249,14 @@ namespace krikkel::NCurses
int PtyWindow::refresh()
{
lock_guard nCursesLock(*writeToNCursesMutex);
lock_guard nCursesLock(*ncursesMutex);
move(cursorY, cursorX);
return NCursesWindow::refresh();
}
/// @todo potential racing condition where drawing into terminal while
/// resizing?
int PtyWindow::wresize(int rows, int cols)
int PtyWindow::resize(int rows, int cols)
{
{
lock_guard writeLock(writeToPseudoTerminalMutex);
@ -269,8 +269,8 @@ namespace krikkel::NCurses
vterm_set_size(pseudoTerminal, rows, cols);
}
{
lock_guard nCursesLock(*writeToNCursesMutex);
return NCursesWindow::wresize(rows, cols);
lock_guard nCursesLock(*ncursesMutex);
return Window::wresize(rows, cols);
}
}

View file

@ -0,0 +1,63 @@
/**
* @author Christian Burger (christian@krikkel.de)
*/
#include <NCurses/VerticalTilingWindowManager.hpp>
#include <NCurses/Window.hpp>
#include <ncursesw/ncurses.h>
#include <algorithm>
namespace krikkel::NCurses
{
using std::list;
using std::mutex;
using std::lock_guard;
using std::find;
VerticalTilingWindowManager::VerticalTilingWindowManager(NCursesWindow *rootWindow, mutex *ncursesMutex)
: rootWindow(rootWindow), ncursesMutex(ncursesMutex)
{}
void VerticalTilingWindowManager::addWindow(Window *window)
{
stack.push_back(window);
}
void VerticalTilingWindowManager::refresh()
{
rootWindow->refresh();
for(Window *window : stack)
window->refresh();
}
void VerticalTilingWindowManager::updateLayout()
{
int availableWidth = rootWindow->width();
int availableHeight = rootWindow->height();
int windowHeight = availableHeight / stack.size() - 1;
if((windowHeight + 1) * stack.size() < availableHeight)
++windowHeight;
list<Window *>::iterator it = stack.begin();
uint16_t y = 0;
for(size_t index = 0
; index < stack.size() - 1
; ++index)
{
resizeWindowInStack(*it++, y, windowHeight, availableWidth);
y += windowHeight;
{
lock_guard lock(*ncursesMutex);
rootWindow->move(y++, 0);
rootWindow->hline(availableWidth);
}
}
resizeWindowInStack(*it, y, availableHeight - y, availableWidth);
}
void VerticalTilingWindowManager::resizeWindowInStack(Window *window, uint16_t y, uint16_t height, uint16_t width)
{
window->resize(height, width);
window->mvwin(y, 0);
}
}

View file

@ -3,9 +3,17 @@
*/
#include <NCurses/Window.hpp>
#include <NCurses/VerticalTilingWindowManager.hpp>
namespace krikkel::NCurses
{
Window::Window(VerticalTilingWindowManager *windowManager)
: NCursesWindow(0, 0, 0, 0)
{
windowManager->addWindow(this);
windowManager->updateLayout();
}
Window::Window(int lines, int columns, int y, int x)
: NCursesWindow(lines, columns, y, x)
{}
@ -37,4 +45,9 @@ namespace krikkel::NCurses
return SingleUserInput(result, input);
}
int Window::resize(int rows, int cols)
{
return NCursesWindow::wresize(rows, cols);
}
}

View file

@ -1,12 +1,12 @@
/**
* @brief `ncurses` window displaying contents of a pseudo terminal
* @author Christian Burger (christian@krikkel.de)
* @todo remove all invalid constructors
*/
#ifndef __WINDOW_H__
#define __WINDOW_H__
#include "SingleUserInput.hpp"
#include "Window.hpp"
#include <cursesw.h>
@ -21,7 +21,7 @@ namespace krikkel::NCurses
class PtyWindow : public Window
{
public:
PtyWindow(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x);
PtyWindow(std::mutex *ncursesMutex, int lines, int columns, int y, int x);
~PtyWindow();
int getFdPtyClient() const;
@ -30,14 +30,14 @@ namespace krikkel::NCurses
void writeKeyToClient(VTermKey key);
int refresh() override;
int wresize(int rows, int cols);
virtual int resize(int rows, int cols) override;
private:
int fdPtyHost, fdPtyClient;
struct termios terminalParameters;
VTerm *pseudoTerminal;
std::mutex writeToPseudoTerminalMutex;
std::mutex *writeToNCursesMutex;
std::mutex *ncursesMutex;
VTermScreen *pseudoTerminalScreen;
static VTermScreenCallbacks screenCallbacks;
/// @todo one line is at most 4096 chars long

View file

@ -0,0 +1,35 @@
/**
* @brief Window manager
* @author Christian Burger (christian@krikkel.de)
*/
#ifndef C10F5DF3_1DB4_4714_A84D_115F492F5CDC
#define C10F5DF3_1DB4_4714_A84D_115F492F5CDC
#include <ncursesw/cursesw.h>
#include <list>
#include <mutex>
namespace krikkel::NCurses
{
class Window;
class VerticalTilingWindowManager
{
public:
VerticalTilingWindowManager(NCursesWindow *rootWindow, std::mutex *ncursesMutex);
void addWindow(Window *window);
void refresh();
void updateLayout();
private:
NCursesWindow *rootWindow;
std::mutex *ncursesMutex;
std::list<Window *> stack;
void resizeWindowInStack(Window *window, uint16_t y, uint16_t height, uint16_t width);
};
}
#endif /* C10F5DF3_1DB4_4714_A84D_115F492F5CDC */

View file

@ -36,9 +36,12 @@ inline int UNDEF(get_wch)(wint_t *character) { get_wch(character); }
namespace krikkel::NCurses
{
class VerticalTilingWindowManager;
class Window : public NCursesWindow
{
public:
Window(VerticalTilingWindowManager *windowManager);
Window(int lines, int columns, int y, int x);
int addnwstr(const wchar_t *wstr, int n);
int add_wch(const cchar_t *character);
@ -46,6 +49,7 @@ namespace krikkel::NCurses
int get_wch(wint_t *character);
SingleUserInput readSingleUserInput();
virtual int resize(int rows, int cols);
};
}