/*
*/
+#define __STDC_LIMIT_MACROS
#include <ipc.hpp>
#include <list>
#include <IIPCChannel.hpp>
-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
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)
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()
extern "C" {
#include <acess/sys.h>
#include <acess/devices/pty.h>
+#include <acess/devices/pty_cmds.h>
+#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");
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