Usermode/AxWin4 - Shared buffers working, added DrawCtrl code
authorJohn Hodge <[email protected]>
Mon, 18 Aug 2014 23:44:28 +0000 (07:44 +0800)
committerJohn Hodge <[email protected]>
Mon, 18 Aug 2014 23:44:28 +0000 (07:44 +0800)
Usermode/Applications/axwin4_src/Notes.txt
Usermode/Applications/axwin4_src/Server/CWindow.cpp
Usermode/Applications/axwin4_src/Server/Makefile
Usermode/Applications/axwin4_src/Server/compositor.cpp
Usermode/Applications/axwin4_src/Server/draw_control.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/draw_control.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/ipc.hpp
Usermode/Applications/axwin4_src/Server/ipc.cpp
Usermode/Applications/axwin4_src/UI/main.c

index 83eff4c..ee09686 100644 (file)
@@ -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
index f70db32..32ff4f6 100644 (file)
@@ -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()
 {
index 0d78e9c..cb306b8 100644 (file)
@@ -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++
index 699b6a2..7a18747 100644 (file)
@@ -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 (file)
index 0000000..264165f
--- /dev/null
@@ -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 <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
+
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 (file)
index 0000000..3797e2e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ */
+#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
+
index 8e1c4aa..729f153 100644 (file)
@@ -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);
 
index fcd0eb9..4c5da25 100644 (file)
@@ -1,4 +1,9 @@
 /*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * ipc.cpp
+ * - Client-Server communication (dispatch)
  */
 #define __STDC_LIMIT_MACROS
 #include <ipc.hpp>
@@ -13,6 +18,7 @@ extern "C" {
 #include <assert.h>
 };
 #include <CIPCChannel_AcessIPCPipe.hpp>
+#include <draw_control.hpp>
 
 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
index 54eae0f..b00ce26 100644 (file)
@@ -8,36 +8,74 @@
 #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);
+}
+

UCC git Repository :: git.ucc.asn.au