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
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)
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()
{
OBJ += CClient.o
OBJ += CIPCChannel_AcessIPCPipe.o
OBJ += CRect.o CSurface.o
+OBJ += draw_control.o
BIN := AxWinServer
LDFLAGS += -lc++
{
// 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 );
}
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
--- /dev/null
+/*
+ * 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 <draw_control.hpp>
+
+// === CODE ===
+namespace AxWin {
+
+CControl::CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector<uint32_t>&& 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<uint32_t> 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<uint32_t>& 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<uint32_t> {
+ 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<uint32_t> {
+ 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
+
--- /dev/null
+/*
+ */
+#ifndef _DRAW_CONTROL_HPP_
+#define _DRAW_CONTROL_HPP_
+
+#include <vector>
+#include <string>
+#include <cstdint>
+#include <CSurface.hpp>
+
+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<uint32_t> m_data;
+public:
+ CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector<uint32_t>&& 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<uint32_t>& scanline, const CRect& rect, const uint32_t* ctrl_line) const;
+};
+
+
+}
+
+#endif
+
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);
/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * ipc.cpp
+ * - Client-Server communication (dispatch)
*/
#define __STDC_LIMIT_MACROS
#include <ipc.hpp>
#include <assert.h>
};
#include <CIPCChannel_AcessIPCPipe.hpp>
+#include <draw_control.hpp>
namespace AxWin {
namespace IPC {
}
-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");
}
void HandleMessage_Nop(CClient& client, CDeserialiser& message)
{
+ // Do nothing
}
void HandleMessage_Reply(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) {
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();
}
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");
}
[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
#include <axwin4/axwin.h>
#include <assert.h>
+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);
+}
+