From: John Hodge Date: Sat, 24 May 2014 09:19:54 +0000 (+0800) Subject: Usermode/AxWin4 - Server implemenation moving along X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=47296e890b2b09cbc46db30d7fe2aeeae11a6d4a;p=tpg%2Facess2.git Usermode/AxWin4 - Server implemenation moving along --- diff --git a/Usermode/Applications/Makefile.cfg b/Usermode/Applications/Makefile.cfg index 583ae582..e1703297 100644 --- a/Usermode/Applications/Makefile.cfg +++ b/Usermode/Applications/Makefile.cfg @@ -5,8 +5,6 @@ _appsdir := $(dir $(lastword $(MAKEFILE_LIST))) include $(_appsdir)../Makefile.cfg -CXXFLAGS += -std=gnu++11 - ifeq ($(ARCHDIR),native) ASFLAGS = -felf CPPFLAGS = -Wall @@ -23,6 +21,7 @@ endif -include $(_appsdir)../common_settings.mk LDFLAGS += -rpath-link $(OUTPUTDIR)Libs +CXXFLAGS += -std=gnu++11 # Extra-verbose errors! #CFLAGS += -Wall -Wextra -Wwrite-strings -Wshadow -Wswitch-default -Wswitch-enum -Wstrict-overflow=5 -Wfloat-equal -Wundef -Wmissing-declarations -Wlogical-op -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Wsync-nand -Wunused -Wstrict-overflow=5 -Wfloat-equal -Wundef -Wno-endif-labels -Wshadow -Wunsafe-loop-optimizations -Wbad-function-cast -Wc++-compat -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-declarations -Wnormalized=nfc -Wpacked -Wpadded -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wdisabled-optimization -Woverlength-strings diff --git a/Usermode/Applications/axwin4_src/Server/CWindow.cpp b/Usermode/Applications/axwin4_src/Server/CWindow.cpp index 4d1416ed..bd952aa0 100644 --- a/Usermode/Applications/axwin4_src/Server/CWindow.cpp +++ b/Usermode/Applications/axwin4_src/Server/CWindow.cpp @@ -6,13 +6,16 @@ * - Window */ #include +#include +#include namespace AxWin { -CWindow::CWindow(CClient& client, const ::std::string& name): +CWindow::CWindow(CCompositor& compositor, CClient& client, const ::std::string& name): + m_surface(0,0,0,0), + m_compositor(compositor), m_client(client), - m_name(name), - m_surface(0,0,0,0) + m_name(name) { } @@ -29,11 +32,42 @@ void CWindow::Repaint(const CRect& rect) if( rect.Contains(rgn->m_rect) ) { CRect rel_rect(rect, rgn->m_rect); - rgn->Repaint(); + rgn->Repaint(m_surface, rel_rect); } } #endif } +void CWindow::Show(bool bShow) +{ + assert(!"TODO: CWindow::Show"); +} + +void CWindow::Move(int X, int Y) +{ + assert(!"TODO: CWindow::Move"); +} +void CWindow::Resize(unsigned int W, unsigned int H) +{ + assert(!"TODO: CWindow::Resize"); +} +uint64_t CWindow::ShareSurface() +{ + assert(!"TODO: CWindow::ShareSurface"); + return 0; +} + +void CWindow::MouseButton(int ButtonID, int X, int Y, bool Down) +{ +} + +void CWindow::MouseMove(int NewX, int NewY) +{ +} + +void CWindow::KeyEvent(::uint32_t Scancode, const ::std::string &Translated, bool Down) +{ +} + }; diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp index 61d42e37..40521459 100644 --- a/Usermode/Applications/axwin4_src/Server/compositor.cpp +++ b/Usermode/Applications/axwin4_src/Server/compositor.cpp @@ -6,8 +6,8 @@ * - Window compositor */ #include -#include #include +#include namespace AxWin { @@ -17,9 +17,25 @@ CCompositor::CCompositor(CVideo& video): // } -CWindow* CCompositor::CreateWindow(CClient& client) +CWindow* CCompositor::CreateWindow(CClient& client, const ::std::string& name) { - return new CWindow(client, "TODO"); + return new CWindow(*this, client, name); +} + +bool CCompositor::GetScreenDims(unsigned int ScreenID, unsigned int* W, unsigned int* H) +{ + assert(W && H); + if( ScreenID != 0 ) + { + *W = 0; + *H = 0; + return false; + } + else + { + m_video.GetDims(*W, *H); + return true; + } } void CCompositor::Redraw() @@ -50,6 +66,7 @@ void CCompositor::Redraw() } m_damageRects.clear(); + m_video.Flush(); } void CCompositor::DamageArea(const CRect& area) diff --git a/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp b/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp index 48b17c68..51f04c91 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp @@ -8,6 +8,7 @@ #ifndef _CCOMPOSITOR_H_ #define _CCOMPOSITOR_H_ +#include #include #include #include "CRect.hpp" @@ -45,7 +46,9 @@ class CCompositor public: CCompositor(CVideo& video); - CWindow* CreateWindow(CClient& client); + CWindow* CreateWindow(CClient& client, const ::std::string& name); + + bool GetScreenDims(unsigned int ScrenID, unsigned int *Width, unsigned int *Height); void Redraw(); void DamageArea(const CRect& rect); diff --git a/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp b/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp index 00bc7e87..2248853b 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp @@ -17,14 +17,22 @@ namespace AxWin { class CClient; +class CCompositor; +class CRegion; class CWindow { public: - CWindow(CClient& client, const ::std::string &name); + CWindow(CCompositor& compositor, CClient& client, const ::std::string &name); ~CWindow(); void Repaint(const CRect& rect); + + void Show(bool bShow); + void Move(int X, int Y); + void Resize(unsigned int W, unsigned int H); + + uint64_t ShareSurface(); void MouseButton(int ButtonID, int X, int Y, bool Down); void MouseMove(int NewX, int NewY); @@ -32,9 +40,10 @@ public: CSurface m_surface; private: - const ::std::string m_name; + CCompositor& m_compositor; CClient& m_client; - //::std::list m_regions; + const ::std::string m_name; + ::std::vector m_regions; }; }; // namespace AxWin diff --git a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp index c51c2019..d801953f 100644 --- a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp @@ -8,6 +8,8 @@ #ifndef _IPC_H_ #define _IPC_H_ +#include + extern "C" { #include }; @@ -23,6 +25,16 @@ extern void Initialise(const CConfigIPC& config, CCompositor& compositor); extern int FillSelect(::fd_set& rfds); extern void HandleSelect(::fd_set& rfds); +class CClientFailure: + public ::std::exception +{ + const std::string m_what; +public: + CClientFailure(std::string&& what); + ~CClientFailure() throw(); + const char *what() const throw(); +}; + }; // namespace IPC }; // namespace AxWin diff --git a/Usermode/Applications/axwin4_src/Server/include/ipc_proto.hpp b/Usermode/Applications/axwin4_src/Server/include/ipc_proto.hpp index f78bfbb8..a3464248 100644 --- a/Usermode/Applications/axwin4_src/Server/include/ipc_proto.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/ipc_proto.hpp @@ -12,19 +12,40 @@ namespace AxWin { enum { - IPCMSG_PING, + IPCMSG_NULL, IPCMSG_REPLY, + IPCMSG_PING, + IPCMSG_GETGLOBAL, + IPCMSG_SETGLOBAL, + IPCMSG_CREATEWIN, IPCMSG_CLOSEWIN, IPCMSG_SETWINATTR, IPCMSG_GETWINATTR, - - IPCMSG_RGNADD, - IPCMSG_RGNDEL, - IPCMSG_RGNSETATTR, - IPCMSG_RGNPUSHDATA, - IPCMSG_SENDIPC, + IPCMSG_GETWINBUF, // get a handle to the window's buffer + + // - Window drawing commands + //IPCMSG_DRAWGROUP, // (u16 win, u16 group_id) - (hint) Switch to this group + //IPCMSG_CLEAR, // (u16 win) - (hint) Clear current drawing group + IPCMSG_PUSHDATA, // (u16 win, u16 x, u16 y, u16 w, u16 h, void data) + IPCMSG_BLIT, // (win, sx, sy, dx, dy, w, h) - Blit locally + IPCMSG_DRAWCTL, // (win, x, y, w, h, ctlid) - Draw + IPCMSG_DRAWTEXT, // (win, x, y, fontid, text) - Draw text using an internal font +}; + +enum eIPC_GlobalAttrs +{ + IPC_GLOBATTR_SCREENDIMS, // Screen dimensions - Readonly + IPC_GLOBATTR_MAXAREA, // Maximum window area for screen (hint, not enforced) +}; + +enum eIPC_WinAttrs +{ + IPC_WINATTR_SHOW, + IPC_WINATTR_FLAGS, // Decoration enabled, always-on-top + IPC_WINATTR_POSITION, + IPC_WINATTR_DIMENSIONS, }; }; diff --git a/Usermode/Applications/axwin4_src/Server/include/serialisation.hpp b/Usermode/Applications/axwin4_src/Server/include/serialisation.hpp index f0cc600c..ca397b4e 100644 --- a/Usermode/Applications/axwin4_src/Server/include/serialisation.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/serialisation.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace AxWin { @@ -25,6 +26,8 @@ public: CDeserialiser(size_t Length, const void *Buffer); ::uint8_t ReadU8(); ::uint16_t ReadU16(); + ::int16_t ReadS16(); + ::std::string ReadString(); }; class CSerialiser diff --git a/Usermode/Applications/axwin4_src/Server/include/video.hpp b/Usermode/Applications/axwin4_src/Server/include/video.hpp index baa75d24..539410b4 100644 --- a/Usermode/Applications/axwin4_src/Server/include/video.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/video.hpp @@ -18,10 +18,19 @@ class CVideo int m_fd; unsigned int m_width; unsigned int m_height; + int m_bufferFormat; public: CVideo(const CConfigVideo& config); - + + void GetDims(unsigned int& w, unsigned int& h); + void BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width); + void Flush(); + +private: + void SetBufFormat(unsigned int FormatID); + void SetCursorBitmap(); + void SetCursorPos(int X, int Y); }; }; diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp index 2a633500..f842578b 100644 --- a/Usermode/Applications/axwin4_src/Server/ipc.cpp +++ b/Usermode/Applications/axwin4_src/Server/ipc.cpp @@ -1,5 +1,6 @@ /* */ +#define __STDC_LIMIT_MACROS #include #include #include @@ -67,46 +68,9 @@ void DeregisterClient(CClient& client) -typedef void MessageHandler_op_t(CClient& client, CDeserialiser& message); -MessageHandler_op_t HandleMessage_Ping; -MessageHandler_op_t HandleMessage_GetWindowAttr; -MessageHandler_op_t HandleMessage_Reply; -MessageHandler_op_t HandleMessage_CreateWindow; -MessageHandler_op_t HandleMessage_CloseWindow; -MessageHandler_op_t HandleMessage_SetWindowAttr; -MessageHandler_op_t HandleMessage_AddRegion; -MessageHandler_op_t HandleMessage_DelRegion; -MessageHandler_op_t HandleMessage_SetRegionAttr; -MessageHandler_op_t HandleMessage_PushData; -MessageHandler_op_t HandleMessage_SendIPC; - -MessageHandler_op_t *message_handlers[] = { - [IPCMSG_PING] = &HandleMessage_Ping, - [IPCMSG_REPLY] = &HandleMessage_Reply, - - [IPCMSG_CREATEWIN] = &HandleMessage_CreateWindow, - [IPCMSG_CLOSEWIN] = &HandleMessage_CloseWindow, - [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr, - [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr, - - [IPCMSG_RGNADD] = &HandleMessage_AddRegion, - [IPCMSG_RGNDEL] = &HandleMessage_DelRegion, - [IPCMSG_RGNSETATTR] = &HandleMessage_SetRegionAttr, - [IPCMSG_RGNPUSHDATA]= &HandleMessage_PushData, // to a region - [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith inter-process messaging -}; - -void HandleMessage(CClient& client, CDeserialiser& message) +void HandleMessage_Nop(CClient& client, CDeserialiser& message) { - unsigned int command = message.ReadU8(); - if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) { - // Drop, invalid command - return ; - } - - (message_handlers[command])(client, message); } - void HandleMessage_Reply(CClient& client, CDeserialiser& message) { // Reply to a sent message @@ -132,23 +96,100 @@ void HandleMessage_Ping(CClient& client, CDeserialiser& message) client.SendMessage(reply); } +void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message) +{ + uint16_t attr_id = message.ReadU16(); + + CSerialiser reply; + reply.WriteU8(IPCMSG_REPLY); + reply.WriteU8(IPCMSG_GETGLOBAL); + reply.WriteU16(attr_id); + + switch(attr_id) + { + case IPC_GLOBATTR_SCREENDIMS: { + uint8_t screen_id = message.ReadU8(); + unsigned int w, h; + gpCompositor->GetScreenDims(screen_id, &w, &h); + reply.WriteU16( (w <= UINT16_MAX ? w : UINT16_MAX) ); + reply.WriteU16( (h <= UINT16_MAX ? h : UINT16_MAX) ); + break; } + default: + throw IPC::CClientFailure("Bad global attribute ID"); + } + + client.SendMessage(reply); +} + +void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message) +{ + uint16_t attr_id = message.ReadU16(); + + switch(attr_id) + { + case IPC_GLOBATTR_SCREENDIMS: + // Setting readonly + break; + case IPC_GLOBATTR_MAXAREA: + assert(!"TODO: IPC_GLOBATTR_MAXAREA"); + break; + default: + throw IPC::CClientFailure("Bad global attribute ID"); + } +} + void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message) { - uint16_t parent_id = message.ReadU16(); uint16_t new_id = message.ReadU16(); - CWindow* parent = client.GetWindow( parent_id ); + //uint16_t parent_id = message.ReadU16(); + //CWindow* parent = client.GetWindow( parent_id ); + ::std::string name = message.ReadString(); - client.SetWindow( new_id, gpCompositor->CreateWindow(client) ); + client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) ); } -void HandleMessage_CloseWindow(CClient& client, CDeserialiser& message) +void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message) { - assert(!"TODO"); + uint16_t win_id = message.ReadU16(); + + CWindow* win = client.GetWindow(win_id); + if(!win) { + throw IPC::CClientFailure("Bad window"); + } + client.SetWindow(win_id, 0); + + // TODO: Directly inform compositor? + delete win; } void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message) { - assert(!"TODO"); + uint16_t win_id = message.ReadU16(); + uint16_t attr_id = message.ReadU16(); + + CWindow* win = client.GetWindow(win_id); + if(!win) { + throw IPC::CClientFailure("Bad window"); + } + + switch(attr_id) + { + case IPC_WINATTR_DIMENSIONS: { + uint16_t new_w = message.ReadU16(); + uint16_t new_h = message.ReadU16(); + win->Resize(new_w, new_h); + assert(!"TODO: IPC_WINATTR_DIMENSIONS"); + break; } + case IPC_WINATTR_POSITION: { + int16_t new_x = message.ReadS16(); + int16_t new_y = message.ReadS16(); + win->Move(new_x, new_y); + assert(!"TODO: IPC_WINATTR_POSITION"); + break; } + default: + _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id); + throw IPC::CClientFailure("Bad window attr"); + } } void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message) @@ -156,31 +197,77 @@ void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message) assert(!"TODO"); } -void HandleMessage_AddRegion(CClient& client, CDeserialiser& message) +void HandleMessage_SendIPC(CClient& client, CDeserialiser& message) { assert(!"TODO"); } -void HandleMessage_DelRegion(CClient& client, CDeserialiser& message) +void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) { assert(!"TODO"); } -void HandleMessage_SetRegionAttr(CClient& client, CDeserialiser& message) +void HandleMessage_PushData(CClient& client, CDeserialiser& message) { assert(!"TODO"); } - -void HandleMessage_PushData(CClient& client, CDeserialiser& message) +void HandleMessage_Blit(CClient& client, CDeserialiser& message) { assert(!"TODO"); } - -void HandleMessage_SendIPC(CClient& client, CDeserialiser& message) +void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message) +{ + assert(!"TODO"); +} +void HandleMessage_DrawText(CClient& client, CDeserialiser& message) { assert(!"TODO"); } +typedef void MessageHandler_op_t(CClient& client, CDeserialiser& message); + +MessageHandler_op_t *message_handlers[] = { + [IPCMSG_NULL] = &HandleMessage_Nop, + [IPCMSG_REPLY] = &HandleMessage_Reply, + [IPCMSG_PING] = &HandleMessage_Ping, + [IPCMSG_GETGLOBAL] = &HandleMessage_GetGlobalAttr, + [IPCMSG_SETGLOBAL] = &HandleMessage_SetGlobalAttr, + + [IPCMSG_CREATEWIN] = &HandleMessage_CreateWindow, + [IPCMSG_CLOSEWIN] = &HandleMessage_DestroyWindow, + [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr, + [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr, + [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith IPC + [IPCMSG_GETWINBUF] = &HandleMessage_GetWindowBuffer, + [IPCMSG_PUSHDATA] = &HandleMessage_PushData, // to a window's buffer + [IPCMSG_BLIT] = &HandleMessage_Blit, // Copy data from one part of the window to another + [IPCMSG_DRAWCTL] = &HandleMessage_DrawCtl, // Draw a control + [IPCMSG_DRAWTEXT] = &HandleMessage_DrawText, // Draw text +}; + +void HandleMessage(CClient& client, CDeserialiser& message) +{ + unsigned int command = message.ReadU8(); + if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) { + // Drop, invalid command + return ; + } + + (message_handlers[command])(client, message); +} + +CClientFailure::CClientFailure(std::string&& what): + m_what(what) +{ +} +const char *CClientFailure::what() const throw() +{ + return m_what.c_str(); +} +CClientFailure::~CClientFailure() throw() +{ +} + }; // namespace IPC IIPCChannel::~IIPCChannel() diff --git a/Usermode/Applications/axwin4_src/Server/main.cpp b/Usermode/Applications/axwin4_src/Server/main.cpp index 01178069..acea9275 100644 --- a/Usermode/Applications/axwin4_src/Server/main.cpp +++ b/Usermode/Applications/axwin4_src/Server/main.cpp @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) IPC::Initialise(config.m_ipc, *compositor); // - Start root child process (from config) // TODO: Spin up child process - + // - Event loop for( ;; ) { diff --git a/Usermode/Applications/axwin4_src/Server/serialisation.cpp b/Usermode/Applications/axwin4_src/Server/serialisation.cpp index c4338cb6..7d605875 100644 --- a/Usermode/Applications/axwin4_src/Server/serialisation.cpp +++ b/Usermode/Applications/axwin4_src/Server/serialisation.cpp @@ -24,6 +24,16 @@ CDeserialiser::CDeserialiser(size_t Length, const void *Buffer) return 0; } +::int16_t CDeserialiser::ReadS16() +{ + return 0; +} + +::std::string CDeserialiser::ReadString() +{ + return ""; +} + CSerialiser::CSerialiser() { } @@ -32,5 +42,9 @@ void CSerialiser::WriteU8(::uint8_t Value) { } +void CSerialiser::WriteU16(::uint16_t Value) +{ +} + }; // namespace AxWin diff --git a/Usermode/Applications/axwin4_src/Server/video.cpp b/Usermode/Applications/axwin4_src/Server/video.cpp index 6fde7aa0..14fb76df 100644 --- a/Usermode/Applications/axwin4_src/Server/video.cpp +++ b/Usermode/Applications/axwin4_src/Server/video.cpp @@ -12,13 +12,19 @@ extern "C" { #include #include +#include +#include "resources/cursor.h" } namespace AxWin { CVideo::CVideo(const CConfigVideo& config): - m_fd(0) + m_fd(1), + m_width(0), + m_height(0), + m_bufferFormat(PTYBUFFMT_TEXT) { + // Obtain dimensions { if( _SysIOCtl(m_fd, DRV_IOCTL_TYPE, NULL) != DRV_TYPE_TERMINAL ) throw AxWin::InitFailure("stdin isn't a terminal"); @@ -30,14 +36,74 @@ CVideo::CVideo(const CConfigVideo& config): if( m_width == 0 || m_height == 0 ) throw AxWin::InitFailure("Terminal not capable of graphics"); } + + SetCursorBitmap(); + + SetCursorPos( m_width/2, m_height/2 ); + + SetBufFormat(PTYBUFFMT_FB); +} + +void CVideo::GetDims(unsigned int& w, unsigned int& h) +{ + w = m_width; + h = m_height; } void CVideo::BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width) { //_SysWriteAt(m_fd, (dst_y * m_width + dst_x) * 4, width * 4, src); + SetBufFormat(PTYBUFFMT_FB); _SysSeek(m_fd, (dst_y * m_width + dst_x) * 4, SEEK_SET); _SysWrite(m_fd, src, width * 4); } +void CVideo::Flush() +{ + // TODO: Write to a local copy of the framebuffer in BlitLine, and then flush out in this function +} + +void CVideo::SetBufFormat(unsigned int FormatID) +{ + if( m_bufferFormat != FormatID ) + { + + struct ptymode mode = {.OutputMode = FormatID, .InputMode = 0}; + int rv = _SysIOCtl( m_fd, PTY_IOCTL_SETMODE, &mode ); + if( rv ) { + throw ::AxWin::InitFailure("Can't set PTY to framebuffer mode"); + } + + m_bufferFormat = FormatID; + } +} + +void CVideo::SetCursorBitmap() +{ + // Set cursor position and bitmap + struct ptycmd_header hdr = {PTY2D_CMD_SETCURSORBMP,0,0}; + size_t size = sizeof(hdr) + sizeof(cCursorBitmap) + cCursorBitmap.W*cCursorBitmap.H*4; + hdr.len_low = size / 4; + hdr.len_hi = size / (256*4); + + SetBufFormat(PTYBUFFMT_2DCMD); + _SysWrite(m_fd, &hdr, sizeof(hdr)); + _SysDebug("size = %i (%04x:%02x * 4)", size, hdr.len_hi, hdr.len_low); + _SysWrite(m_fd, &cCursorBitmap, size-sizeof(hdr)); +} + +void CVideo::SetCursorPos(int X, int Y) +{ + struct ptycmd_setcursorpos cmd; + cmd.hdr.cmd = PTY2D_CMD_SETCURSORPOS; + cmd.hdr.len_low = sizeof(cmd)/4; + cmd.hdr.len_hi = 0; + cmd.x = X; + cmd.y = Y; + + SetBufFormat(PTYBUFFMT_2DCMD); + _SysWrite(m_fd, &cmd, sizeof(cmd)); +} + }; // namespace AxWin