From cb37616a62753de8a1b8d28e3c4ec3ad9891de1b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 19 Aug 2014 07:44:28 +0800 Subject: [PATCH] Usermode/AxWin4 - Shared buffers working, added DrawCtrl code --- Usermode/Applications/axwin4_src/Notes.txt | 2 +- .../axwin4_src/Server/CWindow.cpp | 17 +- .../Applications/axwin4_src/Server/Makefile | 1 + .../axwin4_src/Server/compositor.cpp | 4 +- .../axwin4_src/Server/draw_control.cpp | 162 ++++++++++++++++++ .../Server/include/draw_control.hpp | 37 ++++ .../axwin4_src/Server/include/ipc.hpp | 2 +- .../Applications/axwin4_src/Server/ipc.cpp | 61 ++++++- Usermode/Applications/axwin4_src/UI/main.c | 68 ++++++-- 9 files changed, 322 insertions(+), 32 deletions(-) create mode 100644 Usermode/Applications/axwin4_src/Server/draw_control.cpp create mode 100644 Usermode/Applications/axwin4_src/Server/include/draw_control.hpp diff --git a/Usermode/Applications/axwin4_src/Notes.txt b/Usermode/Applications/axwin4_src/Notes.txt index 83eff4cc..ee09686b 100644 --- a/Usermode/Applications/axwin4_src/Notes.txt +++ b/Usermode/Applications/axwin4_src/Notes.txt @@ -28,7 +28,7 @@ Windows are composed of multiple regions that conform to several types (see belo Server-side rendering primitives: # Apply to regions, rendered in fixed order, each has an ID > Auto-scaling bitmaps - - Control backed by an image with three five regions per axis + - Control backed by an image with three/five regions per axis Edge Fixed, Fill, Center Fixed, Fill, Edge Fixed - Definition is via two pixel counts (edge width, fill width), rest is derived - Command to switch backing image to another already provided diff --git a/Usermode/Applications/axwin4_src/Server/CWindow.cpp b/Usermode/Applications/axwin4_src/Server/CWindow.cpp index f70db321..32ff4f6b 100644 --- a/Usermode/Applications/axwin4_src/Server/CWindow.cpp +++ b/Usermode/Applications/axwin4_src/Server/CWindow.cpp @@ -27,16 +27,15 @@ CWindow::~CWindow() void CWindow::Repaint(const CRect& rect) { - #if 0 - for( auto rgn : m_regions ) + if( m_is_shown ) { - if( rect.Contains(rgn->m_rect) ) - { - CRect rel_rect(rect, rgn->m_rect); - rgn->Repaint(m_surface, rel_rect); - } + CRect outrect( + m_surface.m_rect.m_x + rect.m_x, + m_surface.m_rect.m_y + rect.m_y, + rect.m_w, rect.m_h + ); + m_compositor.DamageArea(outrect); } - #endif } void CWindow::Show(bool bShow) @@ -58,7 +57,7 @@ void CWindow::Move(int X, int Y) void CWindow::Resize(unsigned int W, unsigned int H) { m_surface.Resize(W, H); - IPC::SendNotify_Dims(m_client, W, H); + IPC::SendMessage_NotifyDims(m_client, W, H); } uint64_t CWindow::ShareSurface() { diff --git a/Usermode/Applications/axwin4_src/Server/Makefile b/Usermode/Applications/axwin4_src/Server/Makefile index 0d78e9c6..cb306b8d 100644 --- a/Usermode/Applications/axwin4_src/Server/Makefile +++ b/Usermode/Applications/axwin4_src/Server/Makefile @@ -10,6 +10,7 @@ OBJ += Common__serialisation.o OBJ += CClient.o OBJ += CIPCChannel_AcessIPCPipe.o OBJ += CRect.o CSurface.o +OBJ += draw_control.o BIN := AxWinServer LDFLAGS += -lc++ diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp index 699b6a24..7a18747a 100644 --- a/Usermode/Applications/axwin4_src/Server/compositor.cpp +++ b/Usermode/Applications/axwin4_src/Server/compositor.cpp @@ -72,7 +72,7 @@ void CCompositor::Redraw() { // TODO: just reblit CRect rel_rect = window->m_surface.m_rect.RelativeIntersection(rect); - //_SysDebug("Reblit (%i,%i) %ix%i", rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h); + _SysDebug("Reblit (%i,%i) %ix%i", rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h); BlitFromSurface( window->m_surface, rel_rect ); //window->Repaint( rel_rect ); } @@ -97,7 +97,7 @@ void CCompositor::BlitFromSurface(const CSurface& dest, const CRect& src_rect) for( unsigned int i = 0; i < src_rect.m_h; i ++ ) { m_video.BlitLine( - dest.GetScanline(src_rect.m_y, src_rect.m_x), + dest.GetScanline(src_rect.m_y+i, src_rect.m_x), dest.m_rect.m_y + src_rect.m_y + i, dest.m_rect.m_x + src_rect.m_x, src_rect.m_w diff --git a/Usermode/Applications/axwin4_src/Server/draw_control.cpp b/Usermode/Applications/axwin4_src/Server/draw_control.cpp new file mode 100644 index 00000000..264165f3 --- /dev/null +++ b/Usermode/Applications/axwin4_src/Server/draw_control.cpp @@ -0,0 +1,162 @@ +/* + * Acess2 GUI v4 + * - By John Hodge (thePowersGang) + * + * draw_control.cpp + * - Common "Control" Drawing + * + * Handles drawing of resizable controls defined by a bitmap and four region sizes + */ +#include + +// === CODE === +namespace AxWin { + +CControl::CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector&& data): + m_edge_x(EdgeX), + m_fill_x(FillX), + m_inner_x(InnerX), + m_edge_y(EdgeY), + m_fill_y(FillY), + m_inner_y(InnerY), + m_data(data) +{ + +} + +void CControl::Render(CSurface& dest, const CRect& rect) const +{ + if( rect.m_w < m_edge_x*2 + m_fill_x*2 + m_inner_x ) + return ; + if( rect.m_h < m_edge_y*2 + m_fill_y*2 + m_inner_y ) + return ; + + const int ctrl_width = m_edge_x + m_fill_x + m_inner_x + (m_inner_x ? m_fill_x : 0) + m_edge_x; + + const int top_fill_end = rect.m_h / 2 - m_inner_y; + const int bot_fill_start = top_fill_end + m_inner_y; + const int bot_fill_end = rect.m_h - m_edge_y; + + ::std::vector scanline( rect.m_w ); + int y = 0; + int base_ofs = 0; + // EdgeY + for( int i = 0; i < m_edge_y; i ++ ) + renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]); + base_ofs += m_edge_y; + // FillY + while( y < top_fill_end ) + { + for( int i = 0; i < m_fill_y && y < top_fill_end; i ++ ) + renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]); + } + base_ofs += m_fill_y; + // InnerY + if( m_inner_y > 0 ) + { + for( int i = 0; i < m_inner_y; i ++ ) + renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]); + base_ofs += m_inner_y; + } + else + { + base_ofs -= m_fill_x; + } + // FillY + while( y < bot_fill_end ) + { + for( int i = 0; i < m_fill_y && y < bot_fill_end; i ++ ) + renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]); + } + base_ofs += m_fill_y; + // EdgeY + for( int i = 0; i < m_edge_y; i ++ ) + renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]); + base_ofs += m_edge_y; +} + +void CControl::renderLine(CSurface& dest, int y, ::std::vector& scanline, const CRect& rect, const uint32_t* ctrl_line) const +{ + const int left_fill_end = rect.m_w / 2 - m_inner_x; + const int right_fill_end = rect.m_w - m_edge_x; + + int x = 0; + int base_ofs = 0; + // EdgeX + for( int i = 0; i < m_edge_x; i ++ ) + scanline[x++] = ctrl_line[base_ofs + i]; + base_ofs += m_edge_x; + // FillX + while( x < left_fill_end ) + { + for( int i = 0; i < m_fill_x && x < left_fill_end; i ++ ) + scanline[x++] = ctrl_line[base_ofs + i]; + } + base_ofs += m_fill_x; + // InnerX + if( m_inner_x > 0 ) + { + for( int i = 0; i < m_inner_x; i ++ ) + scanline[x++] = ctrl_line[base_ofs + i]; + base_ofs += m_inner_x; + } + else + { + base_ofs -= m_fill_x; + } + // FillX + while( x < right_fill_end ) + { + for( int i = 0; i < m_fill_x && x < right_fill_end; i ++ ) + scanline[x++] = ctrl_line[base_ofs + i]; + } + base_ofs += m_fill_x; + // EdgeX + for( int i = 0; i < m_edge_x; i ++ ) + scanline[x++] = ctrl_line[base_ofs + i]; + base_ofs += m_edge_x; + + dest.DrawScanline(rect.m_y + y, rect.m_x, rect.m_w, scanline.data()); +} + +// ---- Standard Controls --- +// Standard button control +CControl StdButton(2, 1, 0, 2, 1, 0, ::std::vector { + 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, + 0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0, + 0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0, + 0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0, + 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, + }); + +// Text Area +CControl StdText(2, 1, 0, 2, 1, 0, ::std::vector { + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000, + 0x000000, 0xA0A0A0, 0xFFFFFF, 0xA0A0A0, 0x000000, + 0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + }); + +const CControl* CControl::GetByName(const ::std::string& name) +{ + if( name == "StdButton" ) + return &StdButton; + if( name == "StdText" ) + return &StdText; + // TODO: Use another exception + return nullptr; +} + +const CControl* CControl::GetByID(uint16_t id) +{ + switch(id) + { + case 0x00: return &StdButton; + case 0x01: return &StdText; + default: return nullptr; + } +} + +}; // AxWin + diff --git a/Usermode/Applications/axwin4_src/Server/include/draw_control.hpp b/Usermode/Applications/axwin4_src/Server/include/draw_control.hpp new file mode 100644 index 00000000..3797e2e9 --- /dev/null +++ b/Usermode/Applications/axwin4_src/Server/include/draw_control.hpp @@ -0,0 +1,37 @@ +/* + */ +#ifndef _DRAW_CONTROL_HPP_ +#define _DRAW_CONTROL_HPP_ + +#include +#include +#include +#include + +namespace AxWin { + +class CControl +{ + unsigned int m_edge_x; + unsigned int m_edge_y; + unsigned int m_fill_x; + unsigned int m_fill_y; + unsigned int m_inner_x; + unsigned int m_inner_y; + ::std::vector m_data; +public: + CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector&& data); + void Render(CSurface& dest, const CRect& rect) const; + + static const CControl* GetByName(const ::std::string& name); + static const CControl* GetByID(uint16_t id); + +private: + void renderLine(CSurface& dest, int y, ::std::vector& scanline, const CRect& rect, const uint32_t* ctrl_line) const; +}; + + +} + +#endif + diff --git a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp index 8e1c4aa4..729f1535 100644 --- a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp @@ -30,7 +30,7 @@ extern void HandleSelect(const ::fd_set& rfds); extern void RegisterClient(CClient& client); extern void DeregisterClient(CClient& client); -extern void SendNotify_Dims(CClient& client, unsigned int W, unsigned int H); +extern void SendMessage_NotifyDims(CClient& client, unsigned int NewW, unsigned int NewH); extern void HandleMessage(CClient& client, CDeserialiser& message); diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp index fcd0eb91..4c5da258 100644 --- a/Usermode/Applications/axwin4_src/Server/ipc.cpp +++ b/Usermode/Applications/axwin4_src/Server/ipc.cpp @@ -1,4 +1,9 @@ /* + * Acess2 GUI v4 + * - By John Hodge (thePowersGang) + * + * ipc.cpp + * - Client-Server communication (dispatch) */ #define __STDC_LIMIT_MACROS #include @@ -13,6 +18,7 @@ extern "C" { #include }; #include +#include namespace AxWin { namespace IPC { @@ -69,7 +75,7 @@ void DeregisterClient(CClient& client) } -void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH) +void SendMessage_NotifyDims(CClient& client, unsigned int NewW, unsigned int NewH) { _SysDebug("TODO: CClient::SendNotify_Dims"); } @@ -77,6 +83,7 @@ void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH) void HandleMessage_Nop(CClient& client, CDeserialiser& message) { + // Do nothing } void HandleMessage_Reply(CClient& client, CDeserialiser& message) { @@ -225,7 +232,7 @@ void HandleMessage_SendIPC(CClient& client, CDeserialiser& message) void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); - _SysDebug("_SetWindowAttr: (%i)", win_id); + _SysDebug("_GetWindowBuffer: (%i)", win_id); CWindow* win = client.GetWindow(win_id); if(!win) { @@ -236,11 +243,32 @@ void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) CSerialiser reply; reply.WriteU8(IPCMSG_REPLY); + reply.WriteU8(IPCMSG_GETWINBUF); reply.WriteU16(win_id); reply.WriteU64(handle); client.SendMessage(reply); } +void HandleMessage_DamageRect(CClient& client, CDeserialiser& message) +{ + uint16_t winid = message.ReadU16(); + uint16_t x = message.ReadU16(); + uint16_t y = message.ReadU16(); + uint16_t w = message.ReadU16(); + uint16_t h = message.ReadU16(); + + _SysDebug("_DamageRect: (%i %i,%i %ix%i)", winid, x, y, w, h); + + CWindow* win = client.GetWindow(winid); + if(!win) { + throw IPC::CClientFailure("_PushData: Bad window"); + } + + CRect area(x,y,w,h); + + win->Repaint(area); +} + void HandleMessage_PushData(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); @@ -272,10 +300,35 @@ void HandleMessage_Blit(CClient& client, CDeserialiser& message) } void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message) { - assert(!"TODO HandleMessage_DrawCtl"); + uint16_t win_id = message.ReadU16(); + uint16_t x = message.ReadU16(); + uint16_t y = message.ReadU16(); + uint16_t w = message.ReadU16(); + uint16_t h = message.ReadU16(); + uint16_t ctrl_id = message.ReadU16(); + + CWindow* win = client.GetWindow(win_id); + if(!win) { + throw IPC::CClientFailure("_DrawCtl: Bad window"); + } + + const CControl* ctrl = CControl::GetByID(ctrl_id); + if(!ctrl) { + throw IPC::CClientFailure("_DrawCtl: Invalid control ID"); + } + + CRect area(x,y,w,h); + ctrl->Render(win->m_surface, area); } void HandleMessage_DrawText(CClient& client, CDeserialiser& message) { + uint16_t win_id = message.ReadU16(); + uint16_t x = message.ReadU16(); + uint16_t y = message.ReadU16(); + uint16_t w = message.ReadU16(); + uint16_t h = message.ReadU16(); + ::std::string str = message.ReadString(); + assert(!"TODO HandleMessage_DrawText"); } @@ -294,7 +347,7 @@ MessageHandler_op_t *message_handlers[] = { [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr, [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith IPC [IPCMSG_GETWINBUF] = &HandleMessage_GetWindowBuffer, - [IPCMSG_DAMAGERECT] = nullptr, + [IPCMSG_DAMAGERECT] = &HandleMessage_DamageRect, [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 diff --git a/Usermode/Applications/axwin4_src/UI/main.c b/Usermode/Applications/axwin4_src/UI/main.c index 54eae0ff..b00ce261 100644 --- a/Usermode/Applications/axwin4_src/UI/main.c +++ b/Usermode/Applications/axwin4_src/UI/main.c @@ -8,36 +8,74 @@ #include #include +tAxWin4_Window *CreateBGWin(int w, int h); +tAxWin4_Window *CreateTaskbar(int w, int h); + // === CODE === int main(int argc, const char *argv[]) { assert( AxWin4_Connect("ipcpipe:///Devices/ipcpipe/axwin4") ); - tAxWin4_Window *bgwin = AxWin4_CreateWindow("background"); - unsigned int w, h; AxWin4_GetScreenDimensions(0, &w, &h); + + tAxWin4_Window *bgwin = CreateBGWin(w, h); + tAxWin4_Window *menu = CreateTaskbar(w, h); + + _SysDebug("Beginning queue"); + while( AxWin4_WaitEventQueue(0) ) + ; + _SysDebug("Clean exit"); + + return 0; +} +tAxWin4_Window *CreateBGWin(int w, int h) +{ + tAxWin4_Window *bgwin = AxWin4_CreateWindow("background"); AxWin4_MoveWindow(bgwin, 0,0); AxWin4_ResizeWindow(bgwin, w,h); AxWin4_SetWindowFlags(bgwin, AXWIN4_WNDFLAG_NODECORATE|AXWIN4_WNDFLAG_KEEPBELOW); - AxWin4_ShowWindow(bgwin, true); - + // Load background image uint32_t *buf = AxWin4_GetWindowBuffer(bgwin); - _SysDebug("buf = %p", buf); - // Load image - uint32_t *image = malloc(w*h*4); - for(size_t i = 0; i < w*h; i ++ ) - image[i] = i*(0x1000000/w*h); + for( size_t y = 0; y < h; y ++ ) + { + for(size_t x = 0; x < w; x ++ ) + { + uint8_t r = y * 256 / h; + uint8_t g = 0; + uint8_t b = x * 256 / w; + buf[y*w+x] = (r << 16) | (g << 8) | b; + } + } + //AxWin4_DamageRect(bgwin, 0, 0, w, h); + AxWin4_ShowWindow(bgwin, true); - //AxWin4_DrawBitmap(bgwin, 0, 0, w, h, (void*)image); + return bgwin; +} - _SysDebug("Beginning queue"); +tAxWin4_Window *CreateTaskbar(int w, int h) +{ + int winheight = 30; + tAxWin4_Window *win = AxWin4_CreateWindow("taskbar"); + AxWin4_MoveWindow(win, 0, 0); + AxWin4_ResizeWindow(win, w, winheight); - while( AxWin4_WaitEventQueue(0) ) - ; - _SysDebug("Clean exit"); + AxWin4_SetWindowFlags(win, AXWIN4_WNDFLAG_NODECORATE); + Taskbar_Redraw(win); + AxWin4_ShowWindow(win, true); - return 0; + return win; } + +void Taskbar_Redraw(tAxWin4_Window *win) +{ + int w = 640; + int h = 30; + AxWin4_DrawControl(win, 0, 0, w, h, 0x01); // Standard button, suitable for a toolbar + AxWin4_DrawControl(win, 5, 5, h-10, h-10, 0x00); // Standard button + + AxWin4_DamageRect(bgwin, 0, 0, w, h); +} + -- 2.20.1