3 * - By John Hodge (thePowersGang)
6 * - Client-Server communication (dispatch)
8 #define __STDC_LIMIT_MACROS
11 #include <IIPCChannel.hpp>
13 #include <CClient.hpp>
14 #include <serialisation.hpp>
15 #include <ipc_proto.hpp>
16 #include <CCompositor.hpp>
20 #include <CIPCChannel_AcessIPCPipe.hpp>
21 #include <draw_control.hpp>
26 CCompositor* gpCompositor;
27 ::std::list<IIPCChannel*> glChannels;
28 //::std::map<uint16_t,CClient*> glClients;
30 void Initialise(const CConfigIPC& config, CCompositor& compositor)
32 gpCompositor = &compositor;
34 ::std::string pipe_basepath = "axwin4";
35 glChannels.push_back( new CIPCChannel_AcessIPCPipe( pipe_basepath ) );
37 //glChannels.push_back( new CIPCChannel_TCP("0.0.0.0:2100") );
39 //for( auto channel : config.m_channels )
41 // channels.push_back( );
45 int FillSelect(fd_set& rfds)
48 for( const auto channel : glChannels )
51 ret = ::std::max(ret, channel->FillSelect(rfds));
56 void HandleSelect(const fd_set& rfds)
58 for( const auto channel : glChannels )
61 channel->HandleSelect(rfds);
65 void RegisterClient(CClient& client)
67 // allocate a client ID, and save
69 //glClients[client.m_id] = &client;
72 void DeregisterClient(CClient& client)
74 //glClients.erase( client.m_id );
78 void SendMessage_NotifyDims(CClient& client, unsigned int NewW, unsigned int NewH)
80 _SysDebug("TODO: CClient::SendNotify_Dims");
84 void HandleMessage_Nop(CClient& client, CDeserialiser& message)
88 void HandleMessage_Reply(CClient& client, CDeserialiser& message)
90 // Reply to a sent message
91 // - Not many messages need server-bound replies
92 int orig_command = message.ReadU8();
96 // Ping reply, mark client as still responding
104 void HandleMessage_Ping(CClient& client, CDeserialiser& message)
106 // A client has asked for a ping, we pong them back
108 reply.WriteU8(IPCMSG_REPLY);
109 reply.WriteU8(IPCMSG_PING);
110 client.SendMessage(reply);
113 void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message)
115 uint16_t attr_id = message.ReadU16();
118 reply.WriteU8(IPCMSG_REPLY);
119 reply.WriteU8(IPCMSG_GETGLOBAL);
120 reply.WriteU16(attr_id);
124 case IPC_GLOBATTR_SCREENDIMS: {
125 uint8_t screen_id = message.ReadU8();
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) );
131 case IPC_GLOBATTR_MAXAREA:
132 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
135 throw IPC::CClientFailure("Bad global attribute ID");
138 client.SendMessage(reply);
141 void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message)
143 uint16_t attr_id = message.ReadU16();
147 case IPC_GLOBATTR_SCREENDIMS:
150 case IPC_GLOBATTR_MAXAREA:
151 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
154 throw IPC::CClientFailure("Bad global attribute ID");
158 void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message)
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();
165 ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str());
166 client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) );
169 void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message)
171 uint16_t win_id = message.ReadU16();
172 _SysDebug("_DestroyWindow: (%i)", win_id);
174 CWindow* win = client.GetWindow(win_id);
176 throw IPC::CClientFailure("_DestroyWindow: Bad window");
178 client.SetWindow(win_id, 0);
180 // TODO: Directly inform compositor?
184 void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message)
186 uint16_t win_id = message.ReadU16();
187 uint16_t attr_id = message.ReadU16();
188 _SysDebug("_SetWindowAttr: (%i, %i)", win_id, attr_id);
190 CWindow* win = client.GetWindow(win_id);
192 throw IPC::CClientFailure("_SetWindowAttr - Bad window");
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);
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);
207 case IPC_WINATTR_SHOW:
208 win->Show( message.ReadU8() != 0 );
210 case IPC_WINATTR_FLAGS:
211 win->SetFlags( message.ReadU8() ); // TODO: U8? why so small?
213 case IPC_WINATTR_TITLE:
214 assert(!"TODO: IPC_WINATTR_TITLE");
217 _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id);
218 throw IPC::CClientFailure("Bad window attr");
222 void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message)
224 assert(!"TODO HandleMessage_GetWindowAttr");
227 void HandleMessage_SendIPC(CClient& client, CDeserialiser& message)
229 assert(!"TODO HandleMessage_SendIPC");
232 void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message)
234 uint16_t win_id = message.ReadU16();
235 _SysDebug("_GetWindowBuffer: (%i)", win_id);
237 CWindow* win = client.GetWindow(win_id);
239 throw IPC::CClientFailure("_PushData: Bad window");
242 uint64_t handle = win->m_surface.GetSHMHandle();
245 reply.WriteU8(IPCMSG_REPLY);
246 reply.WriteU8(IPCMSG_GETWINBUF);
247 reply.WriteU16(win_id);
248 reply.WriteU64(handle);
249 client.SendMessage(reply);
252 void HandleMessage_DamageRect(CClient& client, CDeserialiser& message)
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();
260 _SysDebug("_DamageRect: (%i %i,%i %ix%i)", winid, x, y, w, h);
262 CWindow* win = client.GetWindow(winid);
264 throw IPC::CClientFailure("_PushData: Bad window");
272 void HandleMessage_PushData(CClient& client, CDeserialiser& message)
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);
281 CWindow* win = client.GetWindow(win_id);
283 throw IPC::CClientFailure("_PushData: Bad window");
286 for( unsigned int row = 0; row < h; row ++ )
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);
294 win->DrawScanline(y+row, x, w, scanline_data.data());
297 void HandleMessage_Blit(CClient& client, CDeserialiser& message)
299 assert(!"TODO HandleMessage_Blit");
301 void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message)
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();
311 CWindow* win = client.GetWindow(win_id);
313 throw IPC::CClientFailure("_DrawCtl: Bad window");
316 const CControl* ctrl = CControl::GetByID(ctrl_id);
318 throw IPC::CClientFailure("_DrawCtl: Invalid control ID");
322 ctrl->Render(win->m_surface, area);
324 void HandleMessage_DrawText(CClient& client, CDeserialiser& message)
326 uint16_t win_id = message.ReadU16();
327 uint16_t x = message.ReadU16();
328 uint16_t y = message.ReadU16();
329 uint16_t w = message.ReadU16();
330 uint16_t h = message.ReadU16();
331 ::std::string str = message.ReadString();
333 assert(!"TODO HandleMessage_DrawText");
336 typedef void MessageHandler_op_t(CClient& client, CDeserialiser& message);
338 MessageHandler_op_t *message_handlers[] = {
339 [IPCMSG_NULL] = &HandleMessage_Nop,
340 [IPCMSG_REPLY] = &HandleMessage_Reply,
341 [IPCMSG_PING] = &HandleMessage_Ping,
342 [IPCMSG_GETGLOBAL] = &HandleMessage_GetGlobalAttr,
343 [IPCMSG_SETGLOBAL] = &HandleMessage_SetGlobalAttr,
345 [IPCMSG_CREATEWIN] = &HandleMessage_CreateWindow,
346 [IPCMSG_CLOSEWIN] = &HandleMessage_DestroyWindow,
347 [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
348 [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
349 [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith IPC
350 [IPCMSG_GETWINBUF] = &HandleMessage_GetWindowBuffer,
351 [IPCMSG_DAMAGERECT] = &HandleMessage_DamageRect,
352 [IPCMSG_PUSHDATA] = &HandleMessage_PushData, // to a window's buffer
353 [IPCMSG_BLIT] = &HandleMessage_Blit, // Copy data from one part of the window to another
354 [IPCMSG_DRAWCTL] = &HandleMessage_DrawCtl, // Draw a control
355 [IPCMSG_DRAWTEXT] = &HandleMessage_DrawText, // Draw text
358 void HandleMessage(CClient& client, CDeserialiser& message)
360 unsigned int command = message.ReadU8();
361 if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) {
362 // Drop, invalid command
366 (message_handlers[command])(client, message);
369 CClientFailure::CClientFailure(std::string&& what):
373 const char *CClientFailure::what() const throw()
375 return m_what.c_str();
377 CClientFailure::~CClientFailure() throw()
383 IIPCChannel::~IIPCChannel()
387 }; // namespace AxWin