Usermode/AxWin4 - Debugging quirks in ARCH=native
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / ipc.cpp
1 /*
2  * Acess2 GUI v4
3  * - By John Hodge (thePowersGang)
4  *
5  * ipc.cpp
6  * - Client-Server communication (dispatch)
7  */
8 #define __STDC_LIMIT_MACROS
9 #include <ipc.hpp>
10 #include <list>
11 #include <IIPCChannel.hpp>
12 #include <algorithm>
13 #include <CClient.hpp>
14 #include <serialisation.hpp>
15 #include <ipc_proto.hpp>
16 #include <CCompositor.hpp>
17 extern "C" {
18 #include <assert.h>
19 };
20 #include <CIPCChannel_AcessIPCPipe.hpp>
21 #include <draw_control.hpp>
22
23 namespace AxWin {
24 namespace IPC {
25
26 CCompositor*    gpCompositor;
27 ::std::list<IIPCChannel*>       glChannels;
28 //::std::map<uint16_t,CClient*> glClients;
29
30 void Initialise(const CConfigIPC& config, CCompositor& compositor)
31 {
32         gpCompositor = &compositor;
33         
34         ::std::string pipe_basepath = "axwin4";
35         glChannels.push_back( new CIPCChannel_AcessIPCPipe( pipe_basepath ) );
36
37         //glChannels.push_back( new CIPCChannel_TCP("0.0.0.0:2100") );
38         
39         //for( auto channel : config.m_channels )
40         //{
41         //      channels.push_back(  );
42         //}
43 }
44
45 int FillSelect(fd_set& rfds)
46 {
47         int ret = 0;
48         for( const auto channel : glChannels )
49         {
50                 assert(channel);
51                 ret = ::std::max(ret, channel->FillSelect(rfds));
52         }
53         return ret;
54 }
55
56 void HandleSelect(const fd_set& rfds)
57 {
58         for( const auto channel : glChannels )
59         {
60                 assert(channel);
61                 channel->HandleSelect(rfds);
62         }
63 }
64
65 void RegisterClient(CClient& client)
66 {
67         // allocate a client ID, and save
68         //client.m_id = 123;
69         //glClients[client.m_id] = &client;
70 }
71
72 void DeregisterClient(CClient& client)
73 {
74         //glClients.erase( client.m_id );
75 }
76
77
78 void SendMessage_NotifyDims(CClient& client, unsigned int NewW, unsigned int NewH)
79 {
80         _SysDebug("TODO: CClient::SendNotify_Dims");
81 }
82
83
84 void HandleMessage_Nop(CClient& client, CDeserialiser& message)
85 {
86         // Do nothing
87 }
88 void HandleMessage_Reply(CClient& client, CDeserialiser& message)
89 {
90         // Reply to a sent message
91         // - Not many messages need server-bound replies
92         int orig_command = message.ReadU8();
93         switch(orig_command)
94         {
95         case IPCMSG_PING:
96                 // Ping reply, mark client as still responding
97                 break;
98         default:
99                 // Unexpected reply
100                 break;
101         }
102 }
103
104 void HandleMessage_Ping(CClient& client, CDeserialiser& message)
105 {
106         // A client has asked for a ping, we pong them back
107         CSerialiser     reply;
108         reply.WriteU8(IPCMSG_REPLY);
109         reply.WriteU8(IPCMSG_PING);
110         client.SendMessage(reply);
111 }
112
113 void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message)
114 {
115         uint16_t        attr_id = message.ReadU16();
116         
117         CSerialiser     reply;
118         reply.WriteU8(IPCMSG_REPLY);
119         reply.WriteU8(IPCMSG_GETGLOBAL);
120         reply.WriteU16(attr_id);
121         
122         switch(attr_id)
123         {
124         case IPC_GLOBATTR_SCREENDIMS: {
125                 uint8_t screen_id = message.ReadU8();
126                 unsigned int w, h;
127                 gpCompositor->GetScreenDims(screen_id, &w, &h);
128                 reply.WriteU16( (w <= UINT16_MAX ? w : UINT16_MAX) );
129                 reply.WriteU16( (h <= UINT16_MAX ? h : UINT16_MAX) );
130                 break; }
131         case IPC_GLOBATTR_MAXAREA:
132                 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
133                 break;
134         default:
135                 throw IPC::CClientFailure("Bad global attribute ID");
136         }
137         
138         client.SendMessage(reply);
139 }
140
141 void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message)
142 {
143         uint16_t        attr_id = message.ReadU16();
144         
145         switch(attr_id)
146         {
147         case IPC_GLOBATTR_SCREENDIMS:
148                 // Setting readonly
149                 break;
150         case IPC_GLOBATTR_MAXAREA:
151                 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
152                 break;
153         default:
154                 throw IPC::CClientFailure("Bad global attribute ID");
155         }
156 }
157
158 void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message)
159 {
160         uint16_t        new_id = message.ReadU16();
161         //uint16_t      parent_id = message.ReadU16();
162         //CWindow* parent = client.GetWindow( parent_id );
163         ::std::string   name = message.ReadString();
164         
165         ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str());
166         client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) );
167 }
168
169 void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message)
170 {
171         uint16_t        win_id = message.ReadU16();
172         _SysDebug("_DestroyWindow: (%i)", win_id);
173         
174         CWindow*        win = client.GetWindow(win_id);
175         if(!win) {
176                 throw IPC::CClientFailure("_DestroyWindow: Bad window");
177         }
178         client.SetWindow(win_id, 0);    
179         
180         // TODO: Directly inform compositor?
181         delete win;
182 }
183
184 void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message)
185 {
186         uint16_t        win_id = message.ReadU16();
187         uint16_t        attr_id = message.ReadU16();
188         _SysDebug("_SetWindowAttr: (%i, %i)", win_id, attr_id);
189         
190         CWindow*        win = client.GetWindow(win_id);
191         if(!win) {
192                 throw IPC::CClientFailure("_SetWindowAttr - Bad window");
193         }
194         
195         switch(attr_id)
196         {
197         case IPC_WINATTR_DIMENSIONS: {
198                 uint16_t new_w = message.ReadU16();
199                 uint16_t new_h = message.ReadU16();
200                 win->Resize(new_w, new_h);
201                 break; }
202         case IPC_WINATTR_POSITION: {
203                 int16_t new_x = message.ReadS16();
204                 int16_t new_y = message.ReadS16();
205                 win->Move(new_x, new_y);
206                 break; }
207         case IPC_WINATTR_SHOW:
208                 win->Show( message.ReadU8() != 0 );
209                 break;
210         case IPC_WINATTR_FLAGS:
211                 win->SetFlags( message.ReadU8() );      // TODO: U8? why so small?
212                 break;
213         case IPC_WINATTR_TITLE:
214                 assert(!"TODO: IPC_WINATTR_TITLE");
215                 break;
216         default:
217                 _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id);
218                 throw IPC::CClientFailure("Bad window attr");
219         }
220 }
221
222 void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message)
223 {
224         assert(!"TODO HandleMessage_GetWindowAttr");
225 }
226
227 void HandleMessage_SendIPC(CClient& client, CDeserialiser& message)
228 {
229         assert(!"TODO HandleMessage_SendIPC");
230 }
231
232 void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message)
233 {
234         uint16_t        win_id = message.ReadU16();
235         _SysDebug("_GetWindowBuffer: (%i)", win_id);
236         
237         CWindow*        win = client.GetWindow(win_id);
238         if(!win) {
239                 throw IPC::CClientFailure("_PushData: Bad window");
240         }
241         
242         uint64_t handle = win->m_surface.GetSHMHandle();
243         
244         CSerialiser     reply;
245         reply.WriteU8(IPCMSG_REPLY);
246         reply.WriteU8(IPCMSG_GETWINBUF);
247         reply.WriteU16(win_id);
248         reply.WriteU64(handle);
249         client.SendMessage(reply);
250 }
251
252 void HandleMessage_DamageRect(CClient& client, CDeserialiser& message)
253 {
254         uint16_t        winid = message.ReadU16();
255         uint16_t        x = message.ReadU16();
256         uint16_t        y = message.ReadU16();
257         uint16_t        w = message.ReadU16();
258         uint16_t        h = message.ReadU16();
259         
260         _SysDebug("_DamageRect: (%i %i,%i %ix%i)", winid, x, y, w, h);
261         
262         CWindow*        win = client.GetWindow(winid);
263         if(!win) {
264                 throw IPC::CClientFailure("_PushData: Bad window");
265         }
266         
267         CRect   area(x,y,w,h);
268         
269         win->Repaint(area);
270 }
271
272 void HandleMessage_PushData(CClient& client, CDeserialiser& message)
273 {
274         uint16_t        win_id = message.ReadU16();
275         uint16_t        x = message.ReadU16();
276         uint16_t        y = message.ReadU16();
277         uint16_t        w = message.ReadU16();
278         uint16_t        h = message.ReadU16();
279         _SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h);
280         
281         CWindow*        win = client.GetWindow(win_id);
282         if(!win) {
283                 throw IPC::CClientFailure("_PushData: Bad window");
284         }
285         
286         for( unsigned int row = 0; row < h; row ++ )
287         {
288                 const ::std::vector<uint8_t> scanline_data = message.ReadBuffer();
289                 if( scanline_data.size() != w * 4 ) {
290                         _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)",
291                                 scanline_data.size(), w*4);
292                         continue ;
293                 }
294                 win->DrawScanline(y+row, x, w, scanline_data.data());
295         }
296 }
297 void HandleMessage_Blit(CClient& client, CDeserialiser& message)
298 {
299         assert(!"TODO HandleMessage_Blit");
300 }
301 void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message)
302 {
303         uint16_t        win_id = message.ReadU16();
304         uint16_t        x = message.ReadU16();
305         uint16_t        y = message.ReadU16();
306         uint16_t        w = message.ReadU16();
307         uint16_t        h = message.ReadU16();
308         uint16_t        ctrl_id = message.ReadU16();
309         uint16_t        frame = message.ReadU16();
310         _SysDebug("_DrawCtl: (%i, (%i,%i) %ix%i %i %06x)", win_id, x, y, w, h, ctrl_id, frame);
311         
312         CWindow*        win = client.GetWindow(win_id);
313         if(!win) {
314                 throw IPC::CClientFailure("_DrawCtl: Bad window");
315         }
316         
317         const CControl* ctrl = CControl::GetByID(ctrl_id);
318         if(!ctrl) {
319                 throw IPC::CClientFailure("_DrawCtl: Invalid control ID");
320         }
321         
322         CRect   area(x,y,w,h);
323         ctrl->Render(win->m_surface, area);
324 }
325 void HandleMessage_DrawText(CClient& client, CDeserialiser& message)
326 {
327         uint16_t        win_id = message.ReadU16();
328         uint16_t        x = message.ReadU16();
329         uint16_t        y = message.ReadU16();
330         uint16_t        w = message.ReadU16();
331         uint16_t        h = message.ReadU16();
332         ::std::string   str = message.ReadString();
333         
334         assert(!"TODO HandleMessage_DrawText");
335 }
336
337 typedef void    MessageHandler_op_t(CClient& client, CDeserialiser& message);
338
339 MessageHandler_op_t     *message_handlers[] = {
340         [IPCMSG_NULL]       = &HandleMessage_Nop,
341         [IPCMSG_REPLY]      = &HandleMessage_Reply,
342         [IPCMSG_PING]       = &HandleMessage_Ping,
343         [IPCMSG_GETGLOBAL]  = &HandleMessage_GetGlobalAttr,
344         [IPCMSG_SETGLOBAL]  = &HandleMessage_SetGlobalAttr,
345         
346         [IPCMSG_CREATEWIN]  = &HandleMessage_CreateWindow,
347         [IPCMSG_CLOSEWIN]   = &HandleMessage_DestroyWindow,
348         [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
349         [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
350         [IPCMSG_SENDIPC]    = &HandleMessage_SendIPC,   // Use the GUI server for low-bandwith IPC
351         [IPCMSG_GETWINBUF]  = &HandleMessage_GetWindowBuffer,
352         [IPCMSG_DAMAGERECT] = &HandleMessage_DamageRect,
353         [IPCMSG_PUSHDATA]   = &HandleMessage_PushData,  // to a window's buffer
354         [IPCMSG_BLIT]       = &HandleMessage_Blit,      // Copy data from one part of the window to another
355         [IPCMSG_DRAWCTL]    = &HandleMessage_DrawCtl,   // Draw a control
356         [IPCMSG_DRAWTEXT]   = &HandleMessage_DrawText,  // Draw text
357 };
358
359 void HandleMessage(CClient& client, CDeserialiser& message)
360 {
361         unsigned int command = message.ReadU8();
362         if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) {
363                 // Drop, invalid command
364                 return ;
365         }
366         
367         (message_handlers[command])(client, message);
368 }
369
370 CClientFailure::CClientFailure(std::string&& what):
371         m_what(what)
372 {
373 }
374 const char *CClientFailure::what() const throw()
375 {
376         return m_what.c_str();
377 }
378 CClientFailure::~CClientFailure() throw()
379 {
380 }
381
382 };      // namespace IPC
383
384 IIPCChannel::~IIPCChannel()
385 {
386 }
387
388 };      // namespace AxWin
389

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