Usermode/AxWin3 - Updated for PTY support
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / ipc.c
1 /*
2  * Acess2 GUI (AxWin) Version 3
3  * - By John Hodge (thePowersGang)
4  * 
5  * ipc.c
6  * - Interprocess communication
7  */
8 #include <common.h>
9 #include <acess/sys.h>
10 #include <net.h>
11 #include <string.h>
12 #include <ipcmessages.h>
13 #include <stdio.h>
14 #include <wm.h>
15 #include <wm_internals.h>
16 #include <wm_hotkeys.h> // Hotkey registration
17 #include <wm_renderer.h>        // Renderer IPC messages
18
19 #define AXWIN_PORT      4101
20
21 #define STATICBUF_SIZE  64
22 #define MAX_WINDOWS_PER_APP     128
23
24 // === TYPES ===
25 typedef struct sIPC_Type        tIPC_Type;
26
27 struct sIPC_Type
28 {
29          int    (*GetIdentSize)(const void *Ident);
30          int    (*CompareIdent)(const void *Ident1, const void *Ident2);
31         void    (*SendMessage)(const void *Ident, size_t Length, const void *Data);
32 };
33
34 struct sIPC_Client
35 {
36         const tIPC_Type *IPCType;
37         const void      *Ident; // Stored after structure
38
39          int    nWindows;
40         tWindow **Windows;
41 };
42
43 // === IMPORTS ===
44 extern tWindow  *gpWM_FocusedWindow;    // Needed for _FocusWindow
45
46 // === PROTOTYPES ===
47 void    IPC_Init(void);
48 void    IPC_FillSelect(int *nfds, fd_set *set);
49 void    IPC_HandleSelect(fd_set *set);
50  int    IPC_Type_Datagram_GetSize(const void *Ident);
51  int    IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2);
52 void    IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data);
53  int    IPC_Type_Sys_GetSize(const void *Ident);
54  int    IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2);
55 void    IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data);
56  int    IPC_Type_IPCPipe_GetSize(const void *Ident);
57  int    IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2);
58 void    IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data);
59 tIPC_Client     *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident);
60 void    IPC_int_DropClient(tIPC_Client *Client);
61 void    IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg);
62
63 // === GLOBALS ===
64 const tIPC_Type gIPC_Type_Datagram = {
65         IPC_Type_Datagram_GetSize,
66         IPC_Type_Datagram_Compare, 
67         IPC_Type_Datagram_Send
68 };
69 const tIPC_Type gIPC_Type_SysMessage = {
70         IPC_Type_Sys_GetSize,
71         IPC_Type_Sys_Compare,
72         IPC_Type_Sys_Send
73 };
74 const tIPC_Type gIPC_Type_IPCPipe = {
75         IPC_Type_IPCPipe_GetSize,
76         IPC_Type_IPCPipe_Compare,
77         IPC_Type_IPCPipe_Send
78 };
79  int    giNetworkFileHandle = -1;
80  int    giIPCPipeHandle = -1;
81  int    giIPC_ClientCount;
82 tIPC_Client     **gIPC_Clients;
83
84 // === CODE ===
85 void IPC_Init(void)
86 {
87          int    tmp;
88         // TODO: Check this
89         giNetworkFileHandle = _SysOpen("/Devices/ip/loop/udp", OPENFLAG_READ);
90         if( giNetworkFileHandle != -1 )
91         {
92                 tmp = AXWIN_PORT;
93                 _SysIOCtl(giNetworkFileHandle, 4, &tmp);        // TODO: Don't hard-code IOCtl number
94         }
95         
96         giIPCPipeHandle = _SysOpen("/Devices/ipcpipe/axwin"/*-$USER*/, OPENFLAG_CREATE);
97         _SysDebug("giIPCPipeHandle = %i", giIPCPipeHandle);
98         if( giIPCPipeHandle == -1 )
99                 _SysDebug("ERROR: Can't create IPCPipe handle");
100 }
101
102 void _setfd(int fd, int *nfds, fd_set *set)
103 {
104         if( fd >= 0 )
105         {
106                 if( fd >= *nfds )       *nfds = fd+1;
107                 FD_SET(fd, set);
108         }
109 }
110
111 void IPC_FillSelect(int *nfds, fd_set *set)
112 {
113         _setfd(giNetworkFileHandle, nfds, set);
114         _setfd(giIPCPipeHandle, nfds, set);
115         for( int i = 0; i < giIPC_ClientCount; i ++ )
116         {
117                 if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
118                         _setfd( *(int*)(gIPC_Clients[i]->Ident), nfds, set );
119         }
120 }
121
122 void IPC_HandleSelect(fd_set *set)
123 {
124         if( giNetworkFileHandle != -1 && FD_ISSET(giNetworkFileHandle, set) )
125         {
126                 char    staticBuf[STATICBUF_SIZE];
127                  int    readlen, identlen;
128                 char    *msg;
129
130                 readlen = _SysRead(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
131                 
132                 identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
133                 msg = staticBuf + identlen;
134
135                 IPC_Handle( IPC_int_GetClient(&gIPC_Type_Datagram, staticBuf), readlen - identlen, (void*)msg);
136                 //_SysDebug("IPC_HandleSelect: UDP handled");
137         }
138         
139         if( giIPCPipeHandle != -1 && FD_ISSET(giIPCPipeHandle, set) )
140         {
141                 int newfd = _SysOpenChild(giIPCPipeHandle, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
142                 _SysDebug("newfd = %i", newfd);
143                 IPC_int_GetClient(&gIPC_Type_IPCPipe, &newfd);
144         }
145         
146         for( int i = 0; i < giIPC_ClientCount; i ++ )
147         {
148                 if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
149                 {
150                          int fd = *(const int*)gIPC_Clients[i]->Ident;
151                         if( FD_ISSET(fd, set) )
152                         {
153                                 char    staticBuf[STATICBUF_SIZE];
154                                 size_t  len;
155                                 len = _SysRead(fd, staticBuf, sizeof(staticBuf));
156                                 if( len == (size_t)-1 ) {
157                                         // TODO: Check errno for EINTR
158                                         IPC_int_DropClient(gIPC_Clients[i]);
159                                         break;
160                                 }
161                                 IPC_Handle( gIPC_Clients[i], len, (void*)staticBuf );
162                         }
163                 }
164         }
165
166         size_t  len;
167         int     tid;
168         while( (len = _SysGetMessage(&tid, 0, NULL)) )
169         {
170                 char    data[len];
171                 _SysGetMessage(NULL, len, data);
172
173                 IPC_Handle( IPC_int_GetClient(&gIPC_Type_SysMessage, &tid), len, (void*)data );
174 //              _SysDebug("IPC_HandleSelect: Message handled");
175         }
176 }
177
178 int IPC_Type_Datagram_GetSize(const void *Ident)
179 {
180         return 4 + Net_GetAddressSize( ((const uint16_t*)Ident)[1] );
181 }
182
183 int IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2)
184 {
185         // Pass the buck :)
186         // - No need to worry about mis-matching sizes, as the size is computed
187         //   from the 3rd/4th bytes, hence it will differ before the size is hit.
188         return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
189 }
190
191 void IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data)
192 {
193          int    identlen = IPC_Type_Datagram_GetSize(Ident);
194         char    tmpbuf[ identlen + Length ];
195         memcpy(tmpbuf, Ident, identlen);        // Header
196         memcpy(tmpbuf + identlen, Data, Length);        // Data
197         // TODO: Handle fragmented packets
198         _SysWrite(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
199 }
200
201 int IPC_Type_Sys_GetSize(const void *Ident)
202 {
203         return sizeof(pid_t);
204 }
205
206 int IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2)
207 {
208         return *(const tid_t*)Ident1 - *(const tid_t*)Ident2;
209 }
210
211 void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data)
212 {
213         _SysSendMessage( *(const tid_t*)Ident, Length, Data );
214 }
215
216 int IPC_Type_IPCPipe_GetSize(const void *Ident)
217 {
218         return sizeof(int);
219 }
220 int IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2)
221 {
222         return *(const int*)Ident1 - *(const int*)Ident2;
223 }
224 void IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data)
225 {
226         size_t rv = _SysWrite( *(const int*)Ident, Data, Length );
227         if(rv != Length) {
228                 _SysDebug("Sent message oversize %x", Length);
229         }
230 }
231
232 // --- Client -> Window Mappings
233 int _CompareClientPtrs(const void *_a, const void *_b)
234 {
235         tIPC_Client     *a = *(tIPC_Client**)_a;
236         tIPC_Client     *b = *(tIPC_Client**)_b;
237
238         ASSERT(a);
239         if(!b)  return -1;
240
241         if(a->IPCType < b->IPCType)     return -1;
242         if(a->IPCType > b->IPCType)     return 1;
243         
244         return a->IPCType->CompareIdent(a->Ident, b->Ident);
245 }
246
247 int IPC_int_BSearchClients(const tIPC_Client *TargetClient, int *Pos)
248 {
249          int    div;
250          int    cmp = -1;
251          int    pos = 0;
252
253         div = giIPC_ClientCount;
254         pos = div/2;
255         while(div > 0)
256         {
257                 div /= 2;
258                 _SysDebug("Cmp with %i [%i] (%p)", pos, div, gIPC_Clients[pos]);
259                 cmp = _CompareClientPtrs(&TargetClient, &gIPC_Clients[pos]);
260 //              _SysDebug("Checking against %i gives %i", pos, cmp);
261                 if(cmp == 0)    break;
262                 if(cmp < 0)
263                         pos -= div;
264                 else
265                         pos += div;
266         }
267         
268         // - Return if found    
269         if(cmp == 0) {
270                 *Pos = pos;
271                 return 1;
272         }
273
274         // Adjust pos to be the index where the new client will be placed
275         if(cmp > 0)     pos ++;
276         *Pos = pos;
277         return 0;
278 }
279
280 tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
281 {
282          int    pos = 0;        // Position where the new client will be inserted
283          int    ident_size;
284         tIPC_Client     *ret;
285
286         // - Search list of registered clients
287         if(giIPC_ClientCount > 0)
288         {
289                 tIPC_Client     target;
290                 target.IPCType = IPCType;
291                 target.Ident = Ident;
292                 if( IPC_int_BSearchClients(&target, &pos) )
293                         return gIPC_Clients[pos];
294         }
295
296
297         // - Create a new client entry
298         ident_size = IPCType->GetIdentSize(Ident);
299 //      _SysDebug("ident_size = %i", ident_size);
300         ret = malloc( sizeof(tIPC_Client) + ident_size );
301         if(!ret)        return NULL;
302         ret->IPCType = IPCType;
303         ret->Ident = ret + 1;   // Get the end of the structure
304         memcpy( (void*)ret->Ident, Ident, ident_size );
305         ret->nWindows = 0;
306         ret->Windows = NULL;
307         
308         // TODO: Register some way of detecting the client disconnecting
309         //       > Wait on the thread / register with kernel somehow
310         //       > Sockets are easier, but UDP is harder. Might get rid of it
311
312         // - Insert
313         giIPC_ClientCount ++;
314         gIPC_Clients = realloc(gIPC_Clients, giIPC_ClientCount*sizeof(tIPC_Client*));
315         memmove(&gIPC_Clients[pos+1], &gIPC_Clients[pos], (giIPC_ClientCount-pos-1) * sizeof(tIPC_Client*));
316         gIPC_Clients[pos] = ret;
317
318         return ret;
319 }
320
321 void IPC_int_DropClient(tIPC_Client *Client)
322 {
323         // Remove from client list
324          int    pos;
325         if( !IPC_int_BSearchClients(Client, &pos) ) {
326                 _SysDebug("IPC_int_DropClient: Can't find client %p", Client);
327                 return ;
328         }
329
330         giIPC_ClientCount --;
331         memmove(&gIPC_Clients[pos], &gIPC_Clients[pos+1], (giIPC_ClientCount-pos)*sizeof(tIPC_Client*));
332
333         // Terminate client's windows
334         // - If there were active windows, show an error?
335          int    nWindowsDestroyed = 0;
336         for(int i = 0; i < Client->nWindows; i ++)
337         {
338                 if( Client->Windows[i] )
339                 {
340                         _SysDebug("Window %p:%i %p still exists", Client, i, Client->Windows[i]);
341                         WM_DestroyWindow(Client->Windows[i]);
342                         nWindowsDestroyed ++;
343                 }
344         }
345         if( nWindowsDestroyed )
346         {
347                 _SysDebug("TODO: Show notice that application exited without destroying windows");
348         }
349         
350         // Free client structure
351         free(Client);
352         _SysDebug("Dropped client %p", Client);
353 }
354
355 tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t WindowID)
356 {
357         if( WindowID == -1 )
358                 return NULL;
359
360         if( WindowID >= Client->nWindows ) {
361                 return NULL;
362         }
363
364         return Client->Windows[WindowID];
365 }
366
367 void IPC_int_SetWindow(tIPC_Client *Client, uint32_t WindowID, tWindow *WindowPtr)
368 {
369         if( WindowID >= MAX_WINDOWS_PER_APP )
370                 return ;
371
372         if( WindowID >= Client->nWindows )
373         {
374                  int    oldCount = Client->nWindows;
375                 Client->nWindows = WindowID + 1;
376                 Client->Windows = realloc(Client->Windows, Client->nWindows*sizeof(tWindow*));
377                 memset( &Client->Windows[oldCount],  0, (Client->nWindows-oldCount)*sizeof(tWindow*) );
378                 _SysDebug("Expanded %p's window list from %i to %i", Client, oldCount, Client->nWindows);
379         }
380
381         _SysDebug("Assigned %p to window %i for %p", WindowPtr, WindowID, Client);      
382         Client->Windows[WindowID] = WindowPtr;
383 }
384
385 // --- IPC Message Handlers ---
386 int IPC_Msg_Ping(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
387 {
388         ASSERT(Msg->ID == IPCMSG_PING);
389         
390         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
391         
392         if( Msg->Size < 4 )     return -1;
393         
394         tIPCMsg_ReturnInt       *ret = (void*)Msg->Data;
395         Msg->ID = IPCMSG_PING;
396         Msg->Size = sizeof(*ret);
397         ret->Value = AXWIN_VERSION;
398         Client->IPCType->SendMessage(Client->Ident, sizeof(*Msg)+sizeof(*ret), Msg);
399         return 0;
400 }
401
402 int IPC_Msg_GetDisplayCount(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
403 {
404         tAxWin_IPCMessage       *ret_hdr;
405         tIPCMsg_ReturnInt       *ret;
406         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
407         
408         ASSERT(Msg->ID == IPCMSG_GETDISPLAYCOUNT);
409
410         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
411         
412         ret_hdr = (void*)buf;
413         ret_hdr->ID = IPCMSG_GETDISPLAYCOUNT;
414         ret_hdr->Flags = 0;
415         ret_hdr->Window = -1;
416         ret_hdr->Size = sizeof(*ret);
417         ret = (void*)ret_hdr->Data;
418         ret->Value = 1; // HARD CODE - Current version only supports one display
419         
420         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
421         return 0;
422 }
423
424 int IPC_Msg_GetDisplayDims(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
425 {
426         tIPCMsg_GetDisplayDims  *info;
427         tAxWin_IPCMessage       *ret_hdr;
428         tIPCMsg_RetDisplayDims  *ret;
429         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
430         
431         ASSERT(Msg->ID == IPCMSG_GETDISPLAYDIMS);
432
433         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
434
435         info = (void*)Msg->Data;        
436
437         ret_hdr = (void*)buf;
438         ret_hdr->ID = IPCMSG_GETDISPLAYDIMS;
439         ret_hdr->Flags = 0;
440         ret_hdr->Window = -1;
441         ret_hdr->Size = sizeof(*ret);
442         ret = (void*)ret_hdr->Data;
443         
444         // HARD CODE! Only one display supported
445         if( info->DisplayID == 0 )
446         {
447                 ret->X = 0;
448                 ret->Y = 0;
449                 ret->W = giScreenWidth;
450                 ret->H = giScreenHeight;
451         }
452         else
453         {
454                 ret->X = 0;     ret->Y = 0;
455                 ret->W = 0;     ret->H = 0;
456         }
457         
458         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
459         return 0;
460 }
461
462 int IPC_Msg_SendMsg(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
463 {
464         tIPCMsg_SendMsg *info = (void*)Msg->Data;
465         tWindow *src, *dest;
466
467         ASSERT(Msg->ID == IPCMSG_SENDMSG);
468         
469         // - Sanity checks
470         if( Msg->Size < sizeof(tIPCMsg_SendMsg) )
471                 return -1;
472         if( Msg->Size < sizeof(tIPCMsg_SendMsg) + info->Length )
473                 return -1;
474         
475         src = IPC_int_GetWindow(Client, Msg->Window);
476         if(!src)        return 1;
477         dest = IPC_int_GetWindow(Client, info->Remote);
478         if(!dest)       return 1;
479
480         WM_SendMessage(src, dest, info->ID, info->Length, info->Data);  
481
482         return 0;
483 }
484
485 int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
486 {
487         tIPCMsg_CreateWin       *info = (void*)Msg->Data;
488         tWindow *newwin, *parent;
489
490         ASSERT(Msg->ID == IPCMSG_CREATEWIN);
491
492         // - Sanity checks
493         //  > +1 is for NULL byte on string
494         if( Msg->Size < sizeof(*info) + 1 ) {
495                 _SysDebug("IPC_Msg_CreateWin: Size check 1 failed");
496                 return -1;
497         }
498         if( info->Renderer[Msg->Size - sizeof(*info) - 1] != '\0' ) {
499                 _SysDebug("IPC_Msg_CreateWin: Size check 2 failed");
500                 _SysDebug("info = {");
501                 _SysDebug("  .NewWinID = %i", info->NewWinID);
502                 _SysDebug("  .RendererArg = %i", info->RendererArg);
503                 _SysDebug("  .Renderer = '%.*s'", Msg->Size - sizeof(*info), info->Renderer);
504                 _SysDebug("}");
505                 return -1;
506         }
507         
508         // - Get the parent window ID
509         parent = IPC_int_GetWindow(Client, Msg->Window);
510
511         // Catch creating a window with an existing ID
512         if( IPC_int_GetWindow(Client, info->NewWinID) )
513                 return 1;
514
515         // - Create the new window, and save its pointer
516         newwin = WM_CreateWindow(parent, Client, info->NewWinID, info->RendererArg, info->Renderer);
517         IPC_int_SetWindow(Client, info->NewWinID, newwin);
518
519         return 0;
520 }
521
522 int IPC_Msg_DestroyWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
523 {
524         tWindow *win;
525         
526         ASSERT(Msg->ID == IPCMSG_DESTROYWIN);
527
528         win = IPC_int_GetWindow(Client, Msg->Window);
529         if( !win )
530                 return 0;
531         
532         WM_DestroyWindow(win);
533         IPC_int_SetWindow(Client, Msg->Window, NULL);
534         return 0;
535 }
536
537 int IPC_Msg_SetWindowTitle(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
538 {
539         tWindow *win;
540
541         ASSERT(Msg->ID == IPCMSG_SETWINTITLE);
542         
543         if( Msg->Size < 1 )     return -1;
544         if( Msg->Data[ Msg->Size-1 ] != '\0' )  return -1;      
545
546         win = IPC_int_GetWindow(Client, Msg->Window);
547         if(!win)        return 1;
548
549         WM_SetWindowTitle(win, Msg->Data);
550
551         return 0;
552 }
553
554 int IPC_Msg_ShowWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
555 {
556         tIPCMsg_Boolean *info = (void*)Msg->Data;
557         tWindow *win;
558         
559         ASSERT(Msg->ID == IPCMSG_SHOWWINDOW);
560         
561         if( Msg->Size < sizeof(*info) ) return -1;
562         
563         win = IPC_int_GetWindow(Client, Msg->Window);
564         if(!win)        return 1;
565
566         WM_ShowWindow(win, !!info->Value);
567         
568         return 0;
569 }
570
571 int IPC_Msg_DecorateWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
572 {
573         tIPCMsg_Boolean *info = (void*)Msg->Data;
574         tWindow *win;
575         
576         if( Msg->Size < sizeof(*info) ) return -1;
577         
578         win = IPC_int_GetWindow(Client, Msg->Window);
579         if(!win)        return 1;
580         
581         WM_DecorateWindow(win, !!info->Value);
582         return 0;
583 }
584
585 int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
586 {
587         tWindow *win;
588
589         ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
590         
591         // Don't allow the focus to be changed unless the client has the focus
592 //      if(!gpWM_FocusedWindow) return 1;
593 //      if(gpWM_FocusedWindow->Client != Client)        return 1;
594
595         win = IPC_int_GetWindow(Client, Msg->Window);
596         if(!win)        return 1;
597
598         WM_FocusWindow(win);
599
600         return 0;
601 }
602
603 int IPC_Msg_SetWinPos(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
604 {
605         tIPCMsg_SetWindowPos    *info = (void*)Msg->Data;
606         tWindow *win;
607         
608         ASSERT(Msg->ID == IPCMSG_SETWINPOS);
609         
610         if(Msg->Size < sizeof(*info))   return -1;
611         
612         win = IPC_int_GetWindow(Client, Msg->Window);
613         if(!win)        return 1;
614         
615         _SysDebug("info = {..., bSetPos=%i,bSetDims=%i}", info->bSetPos, info->bSetDims);
616         
617         if(info->bSetPos)
618                 WM_MoveWindow(win, info->X, info->Y);
619         if(info->bSetDims)
620                 WM_ResizeWindow(win, info->W, info->H);
621         
622         return 0;
623 }
624
625 int IPC_Msg_RegisterAction(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
626 {
627         tIPCMsg_RegAction       *info = (void*)Msg->Data;
628         tWindow *win;
629         
630         ASSERT(Msg->ID == IPCMSG_REGACTION);
631
632         if( Msg->Size < sizeof(*info) + 1 )
633                 return -1;
634         
635         win = IPC_int_GetWindow(Client, Msg->Window);
636         if(!win)        return 1;
637
638         if( strnlen(info->Action, Msg->Size - sizeof(*info)) == Msg->Size - sizeof(*info) )
639                 return 1;
640
641         _SysDebug("RegisterAction %p:%i [%i]\"%s\"",
642                 Client, Msg->Window, info->Index, info->Action
643                 );
644
645         WM_Hotkey_RegisterAction(info->Action, win, info->Index);
646
647         return 0;
648 }
649
650 int (*gIPC_MessageHandlers[])(tIPC_Client *Client, tAxWin_IPCMessage *Msg) = {
651         IPC_Msg_Ping,
652         IPC_Msg_GetDisplayCount,
653         IPC_Msg_GetDisplayDims,
654         IPC_Msg_SendMsg,
655         IPC_Msg_CreateWin,
656         IPC_Msg_DestroyWin,     // Destroy window
657         IPC_Msg_SetWindowTitle,
658         IPC_Msg_ShowWindow,
659         IPC_Msg_DecorateWindow,
660         IPC_Msg_FocusWindow,
661         IPC_Msg_SetWinPos,
662         IPC_Msg_RegisterAction
663 };
664 const int giIPC_NumMessageHandlers = sizeof(gIPC_MessageHandlers)/sizeof(gIPC_MessageHandlers[0]);
665
666 void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg)
667 {
668          int    rv = 0;
669         
670 //      _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
671 //              IPCType, Ident, MsgLen, Msg);
672         
673         if( MsgLen < sizeof(tAxWin_IPCMessage) )
674                 return ;
675         if( MsgLen < sizeof(tAxWin_IPCMessage) + Msg->Size )
676                 return ;
677         
678         if( Msg->Flags & IPCMSG_FLAG_RENDERER )
679         {
680                 tWindow *win = IPC_int_GetWindow(Client, Msg->Window);
681                 if( !win ) {
682                         _SysDebug("WARNING: NULL window in message %i (%x)", Msg->ID, Msg->Window);
683                         return ;
684                 }
685                 tWMRenderer     *renderer = win->Renderer;
686                 if( Msg->ID >= renderer->nIPCHandlers ) {
687                         _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name);
688                         return ;
689                 }
690                 if( !renderer->IPCHandlers[Msg->ID] ) {
691                         _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name);
692                         return ;
693                 }
694                 _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID);
695                 rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data);
696                 if( rv )
697                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
698         }
699         else
700         {
701                 if( Msg->ID >= giIPC_NumMessageHandlers ) {
702                         fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, Client);
703                         _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, Client);
704                         return ;
705                 }
706                 
707                 if( !gIPC_MessageHandlers[ Msg->ID ] ) {
708                         fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
709                         _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
710                         return ;
711                 }
712         
713                 _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
714                 rv = gIPC_MessageHandlers[Msg->ID](Client, Msg);
715                 if( rv )
716                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
717         }
718 }
719
720 // Dispatch a message to the client
721 void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int MsgID, int Len, void *Data)
722 {
723         tAxWin_IPCMessage       *hdr;
724         tIPCMsg_SendMsg         *msg;
725         char    buf[sizeof(*hdr)+sizeof(*msg)+Len];
726         
727         hdr = (void*)buf;
728         msg = (void*)hdr->Data;
729         
730         hdr->ID = IPCMSG_SENDMSG;
731         hdr->Flags = 0;
732         hdr->Size = sizeof(*msg) + Len;
733         hdr->Window = Dst;
734         
735         msg->Remote = Src;
736         msg->ID = MsgID;
737         msg->Length = Len;
738         memcpy(msg->Data, Data, Len);
739         
740         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
741 }
742
743 // --- Server->Client replies
744 void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data)
745 {
746         tAxWin_IPCMessage       *hdr;
747         char    buf[sizeof(*hdr)+Len];
748         
749         hdr = (void*)buf;
750         
751         hdr->ID = MsgID;
752         hdr->Flags = IPCMSG_FLAG_RENDERER;
753         hdr->Size = Len;
754         hdr->Window = WinID;
755         
756         memcpy(hdr->Data, Data, Len);
757         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
758 }
759

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